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