1 // Copyright (c) 2005-2021 Jay Berkenbilt
2 //
3 // This file is part of qpdf.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //   http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 // Versions of qpdf prior to version 7 were released under the terms
18 // of version 2.0 of the Artistic License. At your option, you may
19 // continue to consider qpdf to be licensed under those terms. Please
20 // see the manual for additional information.
21 
22 // This class implements a simple writer for saving QPDF objects to
23 // new PDF files.  See comments through the header file for additional
24 // details.
25 
26 #ifndef QPDFWRITER_HH
27 #define QPDFWRITER_HH
28 
29 #include <qpdf/DLL.h>
30 #include <qpdf/Types.h>
31 
32 #include <stdio.h>
33 #include <string>
34 #include <list>
35 #include <vector>
36 #include <set>
37 #include <map>
38 
39 #include <qpdf/Constants.h>
40 
41 #include <qpdf/QPDFObjectHandle.hh>
42 #include <qpdf/QPDFObjGen.hh>
43 #include <qpdf/QPDFXRefEntry.hh>
44 
45 #include <qpdf/Pl_Buffer.hh>
46 #include <qpdf/PointerHolder.hh>
47 #include <qpdf/Pipeline.hh>
48 #include <qpdf/Buffer.hh>
49 
50 class QPDF;
51 class Pl_Count;
52 class Pl_MD5;
53 
54 class QPDFWriter
55 {
56   public:
57     // Construct a QPDFWriter object without specifying output.  You
58     // must call one of the output setting routines defined below.
59     QPDF_DLL
60     QPDFWriter(QPDF& pdf);
61 
62     // Create a QPDFWriter object that writes its output to a file or
63     // to stdout.  This is equivalent to using the previous
64     // constructor and then calling setOutputFilename().  See
65     // setOutputFilename() for details.
66     QPDF_DLL
67     QPDFWriter(QPDF& pdf, char const* filename);
68 
69     // Create a QPDFWriter object that writes its output to an already
70     // open FILE*.  This is equivalent to calling the first
71     // constructor and then calling setOutputFile().  See
72     // setOutputFile() for details.
73     QPDF_DLL
74     QPDFWriter(QPDF& pdf, char const* description, FILE* file, bool close_file);
75 
76     QPDF_DLL
77     ~QPDFWriter();
78 
79     class QPDF_DLL_CLASS ProgressReporter
80     {
81       public:
~ProgressReporter()82         virtual ~ProgressReporter()
83         {
84         }
85 
86         // This method is called with a value from 0 to 100 to
87         // indicate approximate progress through the write process.
88         // See registerProgressReporter.
89         virtual void reportProgress(int) = 0;
90     };
91 
92     // Setting Output.  Output may be set only one time.  If you don't
93     // use the filename version of the QPDFWriter constructor, you
94     // must call exactly one of these methods.
95 
96     // Passing null as filename means write to stdout.  QPDFWriter
97     // will create a zero-length output file upon construction.  If
98     // write fails, the empty or partially written file will not be
99     // deleted.  This is by design: sometimes the partial file may be
100     // useful for tracking down problems.  If your application doesn't
101     // want the partially written file to be left behind, you should
102     // delete it the eventual call to write fails.
103     QPDF_DLL
104     void setOutputFilename(char const* filename);
105 
106     // Write to the given FILE*, which must be opened by the caller.
107     // If close_file is true, QPDFWriter will close the file.
108     // Otherwise, the caller must close the file.  The file does not
109     // need to be seekable; it will be written to in a single pass.
110     // It must be open in binary mode.
111     QPDF_DLL
112     void setOutputFile(char const* description, FILE* file, bool close_file);
113 
114     // Indicate that QPDFWriter should create a memory buffer to
115     // contain the final PDF file.  Obtain the memory by calling
116     // getBuffer().
117     QPDF_DLL
118     void setOutputMemory();
119 
120     // Return the buffer object containing the PDF file.  If
121     // setOutputMemory() has been called, this method may be called
122     // exactly one time after write() has returned.  The caller is
123     // responsible for deleting the buffer when done.
124     QPDF_DLL
125     Buffer* getBuffer();
126 
127     // Supply your own pipeline object.  Output will be written to
128     // this pipeline, and QPDFWriter will call finish() on the
129     // pipeline.  It is the caller's responsibility to manage the
130     // memory for the pipeline.  The pipeline is never deleted by
131     // QPDFWriter, which makes it possible for you to call additional
132     // methods on the pipeline after the writing is finished.
133     QPDF_DLL
134     void setOutputPipeline(Pipeline*);
135 
136     // Setting Parameters
137 
138     // Set the value of object stream mode.  In disable mode, we never
139     // generate any object streams.  In preserve mode, we preserve
140     // object stream structure from the original file.  In generate
141     // mode, we generate our own object streams.  In all cases, we
142     // generate a conventional cross-reference table if there are no
143     // object streams and a cross-reference stream if there are object
144     // streams.  The default is o_preserve.
145     QPDF_DLL
146     void setObjectStreamMode(qpdf_object_stream_e);
147 
148     // Set value of stream data mode. This is an older interface.
149     // Instead of using this, prefer setCompressStreams() and
150     // setDecodeLevel(). This method is retained for compatibility,
151     // but it does not cover the full range of available
152     // configurations. The mapping between this and the new methods is
153     // as follows:
154     //
155     // qpdf_s_uncompress:
156     //   setCompressStreams(false)
157     //   setDecodeLevel(qpdf_dl_generalized)
158     // qpdf_s_preserve:
159     //   setCompressStreams(false)
160     //   setDecodeLevel(qpdf_dl_none)
161     // qpdf_s_compress:
162     //   setCompressStreams(true)
163     //   setDecodeLevel(qpdf_dl_generalized)
164     //
165     // The default is qpdf_s_compress.
166     QPDF_DLL
167     void setStreamDataMode(qpdf_stream_data_e);
168 
169     // If true, compress any uncompressed streams when writing them.
170     // Metadata streams are a special case and are not compressed even
171     // if this is true. This is true by default for QPDFWriter. If you
172     // want QPDFWriter to leave uncompressed streams uncompressed,
173     // pass false to this method.
174     QPDF_DLL
175     void setCompressStreams(bool);
176 
177     // When QPDFWriter encounters streams, this parameter controls the
178     // behavior with respect to attempting to apply any filters to the
179     // streams when copying to the output. The decode levels are as
180     // follows:
181     //
182     // qpdf_dl_none: Do not attempt to apply any filters. Streams
183     // remain as they appear in the original file. Note that
184     // uncompressed streams may still be compressed on output. You can
185     // disable that by calling setCompressStreams(false).
186     //
187     // qpdf_dl_generalized: This is the default. QPDFWriter will apply
188     // LZWDecode, ASCII85Decode, ASCIIHexDecode, and FlateDecode
189     // filters on the input. When combined with
190     // setCompressStreams(true), which the default, the effect of this
191     // is that streams filtered with these older and less efficient
192     // filters will be recompressed with the Flate filter. By default,
193     // as a special case, if a stream is already compressed with
194     // FlateDecode and setCompressStreams is enabled, the original
195     // compressed data will be preserved. This behavior can be
196     // overridden by calling setRecompressFlate(true).
197     //
198     // qpdf_dl_specialized: In addition to uncompressing the
199     // generalized compression formats, supported non-lossy
200     // compression will also be decoded. At present, this includes
201     // the RunLengthDecode filter.
202     //
203     // qpdf_dl_all: In addition to generalized and non-lossy
204     // specialized filters, supported lossy compression filters will
205     // be applied. At present, this includes DCTDecode (JPEG)
206     // compression. Note that compressing the resulting data with
207     // DCTDecode again will accumulate loss, so avoid multiple
208     // compression and decompression cycles. This is mostly useful for
209     // retrieving image data.
210     QPDF_DLL
211     void setDecodeLevel(qpdf_stream_decode_level_e);
212 
213     // By default, when both the input and output contents of a stream
214     // are compressed with Flate, qpdf does not uncompress and
215     // recompress the stream. Passing true here causes it to do so.
216     // This can be useful if recompressing all streams with a higher
217     // compression level, which can be set by calling the static
218     // method Pl_Flate::setCompressionLevel.
219     QPDF_DLL
220     void setRecompressFlate(bool);
221 
222     // Set value of content stream normalization.  The default is
223     // "false".  If true, we attempt to normalize newlines inside of
224     // content streams.  Some constructs such as inline images may
225     // thwart our efforts.  There may be some cases where this can
226     // damage the content stream.  This flag should be used only for
227     // debugging and experimenting with PDF content streams.  Never
228     // use it for production files.
229     QPDF_DLL
230     void setContentNormalization(bool);
231 
232     // Set QDF mode.  QDF mode causes special "pretty printing" of
233     // PDF objects, adds comments for easier perusing of files.
234     // Resulting PDF files can be edited in a text editor and then run
235     // through fix-qdf to update cross reference tables and stream
236     // lengths.
237     QPDF_DLL
238     void setQDFMode(bool);
239 
240     // Preserve unreferenced objects. The default behavior is to
241     // discard any object that is not visited during a traversal of
242     // the object structure from the trailer.
243     QPDF_DLL
244     void setPreserveUnreferencedObjects(bool);
245 
246     // Always write a newline before the endstream keyword. This helps
247     // with PDF/A compliance, though it is not sufficient for it.
248     QPDF_DLL
249     void setNewlineBeforeEndstream(bool);
250 
251     // Set the minimum PDF version.  If the PDF version of the input
252     // file (or previously set minimum version) is less than the
253     // version passed to this method, the PDF version of the output
254     // file will be set to this value.  If the original PDF file's
255     // version or previously set minimum version is already this
256     // version or later, the original file's version will be used.
257     // QPDFWriter automatically sets the minimum version to 1.4 when
258     // R3 encryption parameters are used, and to 1.5 when object
259     // streams are used.
260     QPDF_DLL
261     void setMinimumPDFVersion(std::string const&, int extension_level = 0);
262 
263     // Force the PDF version of the output file to be a given version.
264     // Use of this function may create PDF files that will not work
265     // properly with older PDF viewers.  When a PDF version is set
266     // using this function, qpdf will use this version even if the
267     // file contains features that are not supported in that version
268     // of PDF.  In other words, you should only use this function if
269     // you are sure the PDF file in question has no features of newer
270     // versions of PDF or if you are willing to create files that old
271     // viewers may try to open but not be able to properly interpret.
272     // If any encryption has been applied to the document either
273     // explicitly or by preserving the encryption of the source
274     // document, forcing the PDF version to a value too low to support
275     // that type of encryption will explicitly disable decryption.
276     // Additionally, forcing to a version below 1.5 will disable
277     // object streams.
278     QPDF_DLL
279     void forcePDFVersion(std::string const&, int extension_level = 0);
280 
281     // Provide additional text to insert in the PDF file somewhere
282     // near the beginning of the file.  This can be used to add
283     // comments to the beginning of a PDF file, for example, if those
284     // comments are to be consumed by some other application.  No
285     // checks are performed to ensure that the text inserted here is
286     // valid PDF.  If you want to insert multiline comments, you will
287     // need to include \n in the string yourself and start each line
288     // with %.  An extra newline will be appended if one is not
289     // already present at the end of your text.
290     QPDF_DLL
291     void setExtraHeaderText(std::string const&);
292 
293     // Causes a deterministic /ID value to be generated. When this is
294     // set, the current time and output file name are not used as part
295     // of /ID generation. Instead, a digest of all significant parts
296     // of the output file's contents is included in the /ID
297     // calculation. Use of a deterministic /ID can be handy when it is
298     // desirable for a repeat of the same qpdf operation on the same
299     // inputs being written to the same outputs with the same
300     // parameters to generate exactly the same results. This feature
301     // is incompatible with encrypted files because, for encrypted
302     // files, the /ID is generated before any part of the file is
303     // written since it is an input to the encryption process.
304     QPDF_DLL
305     void setDeterministicID(bool);
306 
307     // Cause a static /ID value to be generated.  Use only in test
308     // suites.  See also setDeterministicID.
309     QPDF_DLL
310     void setStaticID(bool);
311 
312     // Use a fixed initialization vector for AES-CBC encryption.  This
313     // is not secure.  It should be used only in test suites for
314     // creating predictable encrypted output.
315     QPDF_DLL
316     void setStaticAesIV(bool);
317 
318     // Suppress inclusion of comments indicating original object IDs
319     // when writing QDF files.  This can also be useful for testing,
320     // particularly when using comparison of two qdf files to
321     // determine whether two PDF files have identical content.
322     QPDF_DLL
323     void setSuppressOriginalObjectIDs(bool);
324 
325     // Preserve encryption.  The default is true unless prefilering,
326     // content normalization, or qdf mode has been selected in which
327     // case encryption is never preserved.  Encryption is also not
328     // preserved if we explicitly set encryption parameters.
329     QPDF_DLL
330     void setPreserveEncryption(bool);
331 
332     // Copy encryption parameters from another QPDF object.  If you
333     // want to copy encryption from the object you are writing, call
334     // setPreserveEncryption(true) instead.
335     QPDF_DLL
336     void copyEncryptionParameters(QPDF&);
337 
338     // Set up for encrypted output.  User and owner password both must
339     // be specified.  Either or both may be the empty string.  Note
340     // that qpdf does not apply any special treatment to the empty
341     // string, which makes it possible to create encrypted files with
342     // empty owner passwords and non-empty user passwords or with the
343     // same password for both user and owner.  Some PDF reading
344     // products don't handle such files very well.  Enabling
345     // encryption disables stream prefiltering and content
346     // normalization.  Note that setting R2 encryption parameters sets
347     // the PDF version to at least 1.3, setting R3 encryption
348     // parameters pushes the PDF version number to at least 1.4,
349     // setting R4 parameters pushes the version to at least 1.5, or if
350     // AES is used, 1.6, and setting R5 or R6 parameters pushes the
351     // version to at least 1.7 with extension level 3.
352     //
353     // Note about Unicode passwords: the PDF specification requires
354     // passwords to be encoded with PDF Doc encoding for R <= 4 and
355     // UTF-8 for R >= 5. In all cases, these methods take strings of
356     // bytes as passwords. It is up to the caller to ensure that
357     // passwords are properly encoded. The qpdf command-line tool
358     // tries to do this, as discussed in the manual. If you are doing
359     // this from your own application, QUtil contains many transcoding
360     // functions that could be useful to you, most notably
361     // utf8_to_pdf_doc.
362 
363     // R3 uses RC4, which is a weak cryptographic algorithm. Don't use
364     // it unless you have to.
365     QPDF_DLL
366     void setR2EncryptionParameters(
367 	char const* user_password, char const* owner_password,
368 	bool allow_print, bool allow_modify,
369 	bool allow_extract, bool allow_annotate);
370     // R3 uses RC4, which is a weak cryptographic algorithm. Don't use
371     // it unless you have to.
372     QPDF_DLL
373     void setR3EncryptionParameters(
374 	char const* user_password, char const* owner_password,
375 	bool allow_accessibility, bool allow_extract,
376         bool allow_assemble, bool allow_annotate_and_form,
377         bool allow_form_filling, bool allow_modify_other,
378 	qpdf_r3_print_e print);
379     // R4 uses RC4, which is a weak cryptographic algorithm, when
380     // use_aes=false. Don't use it unless you have to.
381     QPDF_DLL
382     void setR4EncryptionParameters(
383 	char const* user_password, char const* owner_password,
384 	bool allow_accessibility, bool allow_extract,
385         bool allow_assemble, bool allow_annotate_and_form,
386         bool allow_form_filling, bool allow_modify_other,
387 	qpdf_r3_print_e print, bool encrypt_metadata, bool use_aes);
388     // R5 is deprecated.  Do not use it for production use.  Writing
389     // R5 is supported by qpdf primarily to generate test files for
390     // applications that may need to test R5 support.
391     QPDF_DLL
392     void setR5EncryptionParameters(
393 	char const* user_password, char const* owner_password,
394 	bool allow_accessibility, bool allow_extract,
395         bool allow_assemble, bool allow_annotate_and_form,
396         bool allow_form_filling, bool allow_modify_other,
397 	qpdf_r3_print_e print, bool encrypt_metadata);
398     QPDF_DLL
399     void setR6EncryptionParameters(
400 	char const* user_password, char const* owner_password,
401 	bool allow_accessibility, bool allow_extract,
402         bool allow_assemble, bool allow_annotate_and_form,
403         bool allow_form_filling, bool allow_modify_other,
404 	qpdf_r3_print_e print, bool encrypt_metadata_aes);
405 
406     // Pre qpdf 8.4.0 API
407     [[deprecated("see newer API above")]]
408     QPDF_DLL
409     void setR3EncryptionParameters(
410 	char const* user_password, char const* owner_password,
411 	bool allow_accessibility, bool allow_extract,
412 	qpdf_r3_print_e print, qpdf_r3_modify_e modify);
413     [[deprecated("see newer API above")]]
414     QPDF_DLL
415     void setR4EncryptionParameters(
416 	char const* user_password, char const* owner_password,
417 	bool allow_accessibility, bool allow_extract,
418 	qpdf_r3_print_e print, qpdf_r3_modify_e modify,
419 	bool encrypt_metadata, bool use_aes);
420     [[deprecated("see newer API above")]]
421     QPDF_DLL
422     void setR5EncryptionParameters(
423 	char const* user_password, char const* owner_password,
424 	bool allow_accessibility, bool allow_extract,
425 	qpdf_r3_print_e print, qpdf_r3_modify_e modify,
426 	bool encrypt_metadata);
427     [[deprecated("see newer API above")]]
428     QPDF_DLL
429     void setR6EncryptionParameters(
430 	char const* user_password, char const* owner_password,
431 	bool allow_accessibility, bool allow_extract,
432 	qpdf_r3_print_e print, qpdf_r3_modify_e modify,
433 	bool encrypt_metadata_aes);
434 
435     // Create linearized output.  Disables qdf mode, content
436     // normalization, and stream prefiltering.
437     QPDF_DLL
438     void setLinearization(bool);
439 
440     // For debugging QPDF: provide the name of a file to write pass1
441     // of linearization to. The only reason to use this is to debug
442     // QPDF. To linearize, QPDF writes out the file in two passes.
443     // Usually the first pass is discarded, but lots of computations
444     // are made in pass 1. If a linearized file comes out wrong, it
445     // can be helpful to look at the first pass.
446     QPDF_DLL
447     void setLinearizationPass1Filename(std::string const&);
448 
449     // Create PCLm output. This is only useful for clients that know
450     // how to create PCLm files. If a file is structured exactly as
451     // PCLm requires, this call will tell QPDFWriter to write the PCLm
452     // header, create certain unreferenced streams required by the
453     // standard, and write the objects in the required order. Calling
454     // this on an ordinary PDF serves no purpose. There is no
455     // command-line argument that causes this method to be called.
456     QPDF_DLL
457     void setPCLm(bool);
458 
459     // If you want to be notified of progress, derive a class from
460     // ProgressReporter and override the reportProgress method.
461     QPDF_DLL
462     void registerProgressReporter(PointerHolder<ProgressReporter>);
463 
464     // Return the PDF version that will be written into the header.
465     // Calling this method does all the preparation for writing, so it
466     // is an error to call any methods that may cause a change to the
467     // version. Adding new objects to the original file after calling
468     // this may also cause problems. It is safe to update existing
469     // objects or stream contents after calling this method, e.g., to
470     // include the final version number in metadata.
471     QPDF_DLL
472     std::string getFinalVersion();
473 
474     // Write the final file. There is no expectation of being able to
475     // call write() more than once.
476     QPDF_DLL
477     void write();
478 
479     // Return renumbered ObjGen that was written into the final file.
480     // This method can be used after calling write().
481     QPDF_DLL
482     QPDFObjGen getRenumberedObjGen(QPDFObjGen);
483 
484     // Return XRef entry that was written into the final file.
485     // This method can be used after calling write().
486     QPDF_DLL
487     std::map<QPDFObjGen, QPDFXRefEntry> getWrittenXRefTable();
488 
489   private:
490     // flags used by unparseObject
491     static int const f_stream = 	1 << 0;
492     static int const f_filtered =	1 << 1;
493     static int const f_in_ostream =     1 << 2;
494     static int const f_hex_string =     1 << 3;
495     static int const f_no_encryption =  1 << 4;
496 
497     enum trailer_e { t_normal, t_lin_first, t_lin_second };
498 
499     // An reference to a PipelinePopper instance is passed into
500     // activatePipelineStack. When the PipelinePopper goes out of
501     // scope, the pipeline stack is popped. PipelinePopper's
502     // destructor calls finish on the current pipeline and pops the
503     // pipeline stack until the top of stack is a previous active top
504     // of stack, and restores the pipeline to that point. It deletes
505     // any pipelines that it pops. If the bp argument is non-null and
506     // any of the stack items are of type Pl_Buffer, the buffer is
507     // retrieved.
508     class PipelinePopper
509     {
510         friend class QPDFWriter;
511       public:
PipelinePopper(QPDFWriter * qw,PointerHolder<Buffer> * bp=0)512         PipelinePopper(QPDFWriter* qw,
513                        PointerHolder<Buffer>* bp = 0) :
514             qw(qw),
515             bp(bp)
516         {
517         }
518         ~PipelinePopper();
519 
520       private:
521         QPDFWriter* qw;
522         PointerHolder<Buffer>* bp;
523         std::string stack_id;
524     };
525     friend class PipelinePopper;
526 
527     unsigned int bytesNeeded(long long n);
528     void writeBinary(unsigned long long val, unsigned int bytes);
529     void writeString(std::string const& str);
530     void writeBuffer(PointerHolder<Buffer>&);
531     void writeStringQDF(std::string const& str);
532     void writeStringNoQDF(std::string const& str);
533     void writePad(int nspaces);
534     void assignCompressedObjectNumbers(QPDFObjGen const& og);
535     void enqueueObject(QPDFObjectHandle object);
536     void writeObjectStreamOffsets(
537         std::vector<qpdf_offset_t>& offsets, int first_obj);
538     void writeObjectStream(QPDFObjectHandle object);
539     void writeObject(QPDFObjectHandle object, int object_stream_index = -1);
540     void writeTrailer(trailer_e which, int size,
541 		      bool xref_stream, qpdf_offset_t prev,
542                       int linearization_pass);
543     bool willFilterStream(QPDFObjectHandle stream,
544                           bool& compress_stream, bool& is_metadata,
545                           PointerHolder<Buffer>* stream_data);
546     void unparseObject(QPDFObjectHandle object, int level, int flags,
547 		       // for stream dictionaries
548 		       size_t stream_length = 0, bool compress = false);
549     void unparseChild(QPDFObjectHandle child, int level, int flags);
550     void initializeSpecialStreams();
551     void preserveObjectStreams();
552     void generateObjectStreams();
553     std::string getOriginalID1();
554     void generateID();
555     void interpretR3EncryptionParameters(
556 	std::set<int>& bits_to_clear,
557 	char const* user_password, char const* owner_password,
558 	bool allow_accessibility, bool allow_extract,
559         bool allow_assemble, bool allow_annotate_and_form,
560         bool allow_form_filling, bool allow_modify_other,
561 	qpdf_r3_print_e print, qpdf_r3_modify_e modify);
562     void disableIncompatibleEncryption(int major, int minor,
563                                        int extension_level);
564     void parseVersion(std::string const& version, int& major, int& minor) const;
565     int compareVersions(int major1, int minor1, int major2, int minor2) const;
566     void setEncryptionParameters(
567 	char const* user_password, char const* owner_password,
568 	int V, int R, int key_len, std::set<int>& bits_to_clear);
569     void setEncryptionParametersInternal(
570 	int V, int R, int key_len, int P,
571 	std::string const& O, std::string const& U,
572 	std::string const& OE, std::string const& UE, std::string const& Perms,
573 	std::string const& id1, std::string const& user_password,
574         std::string const& encryption_key);
575     void setDataKey(int objid);
576     int openObject(int objid = 0);
577     void closeObject(int objid);
578     QPDFObjectHandle getTrimmedTrailer();
579     void prepareFileForWrite();
580     void enqueueObjectsStandard();
581     void enqueueObjectsPCLm();
582     void indicateProgress(bool decrement, bool finished);
583     void writeStandard();
584     void writeLinearized();
585     void enqueuePart(std::vector<QPDFObjectHandle>& part);
586     void writeEncryptionDictionary();
587     void doWriteSetup();
588     void writeHeader();
589     void writeHintStream(int hint_id);
590     qpdf_offset_t writeXRefTable(
591         trailer_e which, int first, int last, int size);
592     qpdf_offset_t writeXRefTable(
593         trailer_e which, int first, int last, int size,
594         // for linearization
595         qpdf_offset_t prev,
596         bool suppress_offsets,
597         int hint_id,
598         qpdf_offset_t hint_offset,
599         qpdf_offset_t hint_length,
600         int linearization_pass);
601     qpdf_offset_t writeXRefStream(
602         int objid, int max_id, qpdf_offset_t max_offset,
603         trailer_e which, int first, int last, int size);
604     qpdf_offset_t writeXRefStream(
605         int objid, int max_id, qpdf_offset_t max_offset,
606         trailer_e which, int first, int last, int size,
607         // for linearization
608         qpdf_offset_t prev,
609         int hint_id,
610         qpdf_offset_t hint_offset,
611         qpdf_offset_t hint_length,
612         bool skip_compression,
613         int linearization_pass);
614     int calculateXrefStreamPadding(qpdf_offset_t xref_bytes);
615 
616     // When filtering subsections, push additional pipelines to the
617     // stack. When ready to switch, activate the pipeline stack. When
618     // the passed in PipelinePopper goes out of scope, the stack is
619     // popped.
620     Pipeline* pushPipeline(Pipeline*);
621     void activatePipelineStack(PipelinePopper&);
622     void initializePipelineStack(Pipeline *);
623 
624     void adjustAESStreamLength(size_t& length);
625     void pushEncryptionFilter(PipelinePopper&);
626     void pushDiscardFilter(PipelinePopper&);
627     void pushMD5Pipeline(PipelinePopper&);
628     void computeDeterministicIDData();
629 
630     void discardGeneration(std::map<QPDFObjGen, int> const& in,
631                            std::map<int, int>& out);
632 
633     class Members
634     {
635         friend class QPDFWriter;
636 
637       public:
638         QPDF_DLL
639         ~Members();
640 
641       private:
642         Members(QPDF& pdf);
643         Members(Members const&);
644 
645         QPDF& pdf;
646         char const* filename;
647         FILE* file;
648         bool close_file;
649         Pl_Buffer* buffer_pipeline;
650         Buffer* output_buffer;
651         bool normalize_content_set;
652         bool normalize_content;
653         bool compress_streams;
654         bool compress_streams_set;
655         qpdf_stream_decode_level_e stream_decode_level;
656         bool stream_decode_level_set;
657         bool recompress_flate;
658         bool qdf_mode;
659         bool preserve_unreferenced_objects;
660         bool newline_before_endstream;
661         bool static_id;
662         bool suppress_original_object_ids;
663         bool direct_stream_lengths;
664         bool encrypted;
665         bool preserve_encryption;
666         bool linearized;
667         bool pclm;
668         qpdf_object_stream_e object_stream_mode;
669         std::string encryption_key;
670         bool encrypt_metadata;
671         bool encrypt_use_aes;
672         std::map<std::string, std::string> encryption_dictionary;
673         int encryption_V;
674         int encryption_R;
675 
676         std::string id1;		// for /ID key of
677         std::string id2;		// trailer dictionary
678         std::string final_pdf_version;
679         int final_extension_level;
680         std::string min_pdf_version;
681         int min_extension_level;
682         std::string forced_pdf_version;
683         int forced_extension_level;
684         std::string extra_header_text;
685         int encryption_dict_objid;
686         std::string cur_data_key;
687         std::list<PointerHolder<Pipeline> > to_delete;
688         Pl_Count* pipeline;
689         std::list<QPDFObjectHandle> object_queue;
690         std::map<QPDFObjGen, int> obj_renumber;
691         std::map<int, QPDFXRefEntry> xref;
692         std::map<int, qpdf_offset_t> lengths;
693         int next_objid;
694         int cur_stream_length_id;
695         size_t cur_stream_length;
696         bool added_newline;
697         int max_ostream_index;
698         std::set<QPDFObjGen> normalized_streams;
699         std::map<QPDFObjGen, int> page_object_to_seq;
700         std::map<QPDFObjGen, int> contents_to_page_seq;
701         std::map<QPDFObjGen, int> object_to_object_stream;
702         std::map<int, std::set<QPDFObjGen> > object_stream_to_objects;
703         std::list<Pipeline*> pipeline_stack;
704         unsigned long long next_stack_id;
705         bool deterministic_id;
706         Pl_MD5* md5_pipeline;
707         std::string deterministic_id_data;
708         bool did_write_setup;
709 
710         // For linearization only
711         std::string lin_pass1_filename;
712         std::map<int, int> obj_renumber_no_gen;
713         std::map<int, int> object_to_object_stream_no_gen;
714 
715         // For progress reporting
716         PointerHolder<ProgressReporter> progress_reporter;
717         int events_expected;
718         int events_seen;
719         int next_progress_report;
720     };
721 
722     // Keep all member variables inside the Members object, which we
723     // dynamically allocate. This makes it possible to add new private
724     // members without breaking binary compatibility.
725     PointerHolder<Members> m;
726 };
727 
728 #endif // QPDFWRITER_HH
729