Commit 7db44e260e5079b1b2647f185a852287ed10799c
1 parent
6408d5cd
Refactor `QPDFWriter`: move configuration logic to `Config` methods, encapsulate…
… parameter handling, and adjust related method calls for improved maintainability and readability.
Showing
3 changed files
with
460 additions
and
158 deletions
libqpdf/QPDFWriter.cc
| ... | ... | @@ -28,6 +28,7 @@ using namespace std::literals; |
| 28 | 28 | using namespace qpdf; |
| 29 | 29 | |
| 30 | 30 | using Encryption = impl::Doc::Encryption; |
| 31 | +using Config = Writer::Config; | |
| 31 | 32 | |
| 32 | 33 | QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default) |
| 33 | 34 | { |
| ... | ... | @@ -305,32 +306,32 @@ namespace qpdf::impl |
| 305 | 306 | void doWriteSetup(); |
| 306 | 307 | void prepareFileForWrite(); |
| 307 | 308 | |
| 308 | - void disableIncompatibleEncryption(int major, int minor, int extension_level); | |
| 309 | - void interpretR3EncryptionParameters( | |
| 310 | - bool allow_accessibility, | |
| 311 | - bool allow_extract, | |
| 312 | - bool allow_assemble, | |
| 313 | - bool allow_annotate_and_form, | |
| 314 | - bool allow_form_filling, | |
| 315 | - bool allow_modify_other, | |
| 316 | - qpdf_r3_print_e print, | |
| 317 | - qpdf_r3_modify_e modify); | |
| 318 | - void setEncryptionParameters(char const* user_password, char const* owner_password); | |
| 319 | - void setEncryptionMinimumVersion(); | |
| 320 | - void parseVersion(std::string const& version, int& major, int& minor) const; | |
| 321 | - int compareVersions(int major1, int minor1, int major2, int minor2) const; | |
| 322 | - void generateID(bool encrypted); | |
| 323 | - std::string getOriginalID1(); | |
| 324 | - void initializeTables(size_t extra = 0); | |
| 325 | - void preserveObjectStreams(); | |
| 326 | - void generateObjectStreams(); | |
| 327 | - void initializeSpecialStreams(); | |
| 328 | - void enqueue(QPDFObjectHandle const& object); | |
| 329 | - void enqueueObjectsStandard(); | |
| 330 | - void enqueueObjectsPCLm(); | |
| 331 | - void enqueuePart(std::vector<QPDFObjectHandle>& part); | |
| 332 | - void assignCompressedObjectNumbers(QPDFObjGen og); | |
| 333 | - Dictionary trimmed_trailer(); | |
| 309 | + void disableIncompatibleEncryption(int major, int minor, int extension_level); | |
| 310 | + void interpretR3EncryptionParameters( | |
| 311 | + bool allow_accessibility, | |
| 312 | + bool allow_extract, | |
| 313 | + bool allow_assemble, | |
| 314 | + bool allow_annotate_and_form, | |
| 315 | + bool allow_form_filling, | |
| 316 | + bool allow_modify_other, | |
| 317 | + qpdf_r3_print_e print, | |
| 318 | + qpdf_r3_modify_e modify); | |
| 319 | + void setEncryptionParameters(char const* user_password, char const* owner_password); | |
| 320 | + void setEncryptionMinimumVersion(); | |
| 321 | + void parseVersion(std::string const& version, int& major, int& minor) const; | |
| 322 | + int compareVersions(int major1, int minor1, int major2, int minor2) const; | |
| 323 | + void generateID(bool encrypted); | |
| 324 | + std::string getOriginalID1(); | |
| 325 | + void initializeTables(size_t extra = 0); | |
| 326 | + void preserveObjectStreams(); | |
| 327 | + void generateObjectStreams(); | |
| 328 | + void initializeSpecialStreams(); | |
| 329 | + void enqueue(QPDFObjectHandle const& object); | |
| 330 | + void enqueueObjectsStandard(); | |
| 331 | + void enqueueObjectsPCLm(); | |
| 332 | + void enqueuePart(std::vector<QPDFObjectHandle>& part); | |
| 333 | + void assignCompressedObjectNumbers(QPDFObjGen og); | |
| 334 | + Dictionary trimmed_trailer(); | |
| 334 | 335 | |
| 335 | 336 | // Returns tuple<filter, compress_stream, is_root_metadata> |
| 336 | 337 | std::tuple<const bool, const bool, const bool> |
| ... | ... | @@ -557,75 +558,110 @@ QPDFWriter::setOutputPipeline(Pipeline* p) |
| 557 | 558 | void |
| 558 | 559 | QPDFWriter::setObjectStreamMode(qpdf_object_stream_e mode) |
| 559 | 560 | { |
| 560 | - m->cfg.object_stream_mode_ = mode; | |
| 561 | + m->cfg.object_streams(mode); | |
| 561 | 562 | } |
| 562 | 563 | |
| 563 | 564 | void |
| 564 | 565 | QPDFWriter::setStreamDataMode(qpdf_stream_data_e mode) |
| 565 | 566 | { |
| 567 | + m->cfg.stream_data(mode); | |
| 568 | +} | |
| 569 | + | |
| 570 | +Config& | |
| 571 | +Config::stream_data(qpdf_stream_data_e mode) | |
| 572 | +{ | |
| 566 | 573 | switch (mode) { |
| 567 | 574 | case qpdf_s_uncompress: |
| 568 | - m->cfg.stream_decode_level_ = std::max(qpdf_dl_generalized, m->cfg.stream_decode_level_); | |
| 569 | - m->cfg.compress_streams_ = false; | |
| 570 | - break; | |
| 575 | + stream_decode_level(std::max(qpdf_dl_generalized, stream_decode_level_)); | |
| 576 | + compress_streams(false); | |
| 577 | + return *this; | |
| 571 | 578 | |
| 572 | 579 | case qpdf_s_preserve: |
| 573 | - m->cfg.stream_decode_level_ = qpdf_dl_none; | |
| 574 | - m->cfg.compress_streams_ = false; | |
| 575 | - break; | |
| 580 | + stream_decode_level(qpdf_dl_none); | |
| 581 | + compress_streams(false); | |
| 582 | + return *this; | |
| 576 | 583 | |
| 577 | 584 | case qpdf_s_compress: |
| 578 | - m->cfg.stream_decode_level_ = std::max(qpdf_dl_generalized, m->cfg.stream_decode_level_); | |
| 579 | - m->cfg.compress_streams_ = true; | |
| 580 | - break; | |
| 585 | + stream_decode_level(std::max(qpdf_dl_generalized, stream_decode_level_)); | |
| 586 | + compress_streams(true); | |
| 581 | 587 | } |
| 582 | - m->cfg.stream_decode_level_set_ = true; | |
| 583 | - m->cfg.compress_streams_set_ = true; | |
| 588 | + return *this; | |
| 584 | 589 | } |
| 585 | 590 | |
| 586 | 591 | void |
| 587 | 592 | QPDFWriter::setCompressStreams(bool val) |
| 588 | 593 | { |
| 589 | - m->cfg.compress_streams_ = val; | |
| 590 | - m->cfg.compress_streams_set_ = true; | |
| 594 | + m->cfg.compress_streams(val); | |
| 595 | +} | |
| 596 | + | |
| 597 | +Config& | |
| 598 | +Config::compress_streams(bool val) | |
| 599 | +{ | |
| 600 | + if (pclm_) { | |
| 601 | + usage("compress_streams cannot be set when pclm is set"); | |
| 602 | + return *this; | |
| 603 | + } | |
| 604 | + compress_streams_set_ = true; | |
| 605 | + compress_streams_ = val; | |
| 606 | + return *this; | |
| 591 | 607 | } |
| 592 | 608 | |
| 593 | 609 | void |
| 594 | 610 | QPDFWriter::setDecodeLevel(qpdf_stream_decode_level_e val) |
| 595 | 611 | { |
| 596 | - m->cfg.stream_decode_level_ = val; | |
| 597 | - m->cfg.stream_decode_level_set_ = true; | |
| 612 | + m->cfg.stream_decode_level(val); | |
| 613 | +} | |
| 614 | + | |
| 615 | +Config& | |
| 616 | +Config::stream_decode_level(qpdf_stream_decode_level_e val) | |
| 617 | +{ | |
| 618 | + if (pclm_) { | |
| 619 | + usage("stream_decode_level cannot be set when pclm is set"); | |
| 620 | + return *this; | |
| 621 | + } | |
| 622 | + stream_decode_level_set_ = true; | |
| 623 | + stream_decode_level_ = val; | |
| 624 | + return *this; | |
| 598 | 625 | } |
| 599 | 626 | |
| 600 | 627 | void |
| 601 | 628 | QPDFWriter::setRecompressFlate(bool val) |
| 602 | 629 | { |
| 603 | - m->cfg.recompress_flate_ = val; | |
| 630 | + m->cfg.recompress_flate(val); | |
| 604 | 631 | } |
| 605 | 632 | |
| 606 | 633 | void |
| 607 | 634 | QPDFWriter::setContentNormalization(bool val) |
| 608 | 635 | { |
| 609 | - m->cfg.normalize_content_set_ = true; | |
| 610 | - m->cfg.normalize_content_ = val; | |
| 636 | + m->cfg.normalize_content(val); | |
| 611 | 637 | } |
| 612 | 638 | |
| 613 | 639 | void |
| 614 | 640 | QPDFWriter::setQDFMode(bool val) |
| 615 | 641 | { |
| 616 | - m->cfg.qdf_mode_ = val; | |
| 642 | + m->cfg.qdf(val); | |
| 643 | +} | |
| 644 | + | |
| 645 | +Config& | |
| 646 | +Config::qdf(bool val) | |
| 647 | +{ | |
| 648 | + if (pclm_ || linearize_) { | |
| 649 | + usage("qdf cannot be set when linearize or pclm are set"); | |
| 650 | + } | |
| 651 | + qdf_ = val; | |
| 652 | + return *this; | |
| 617 | 653 | } |
| 618 | 654 | |
| 619 | 655 | void |
| 620 | 656 | QPDFWriter::setPreserveUnreferencedObjects(bool val) |
| 621 | 657 | { |
| 622 | - m->cfg.preserve_unreferenced_objects_ = val; | |
| 658 | + m->cfg.preserve_unreferenced(val); | |
| 623 | 659 | } |
| 624 | 660 | |
| 625 | 661 | void |
| 626 | 662 | QPDFWriter::setNewlineBeforeEndstream(bool val) |
| 627 | 663 | { |
| 628 | - m->cfg.newline_before_endstream_ = val; | |
| 664 | + m->cfg.newline_before_endstream(val); | |
| 629 | 665 | } |
| 630 | 666 | |
| 631 | 667 | void |
| ... | ... | @@ -681,31 +717,37 @@ QPDFWriter::setMinimumPDFVersion(PDFVersion const& v) |
| 681 | 717 | void |
| 682 | 718 | QPDFWriter::forcePDFVersion(std::string const& version, int extension_level) |
| 683 | 719 | { |
| 684 | - m->cfg.forced_pdf_version_ = version; | |
| 685 | - m->cfg.forced_extension_level_ = extension_level; | |
| 720 | + m->cfg.forced_pdf_version(version, extension_level); | |
| 686 | 721 | } |
| 687 | 722 | |
| 688 | 723 | void |
| 689 | 724 | QPDFWriter::setExtraHeaderText(std::string const& text) |
| 690 | 725 | { |
| 691 | - m->cfg.extra_header_text_ = text; | |
| 692 | - if (!m->cfg.extra_header_text_.empty() && m->cfg.extra_header_text_.back() != '\n') { | |
| 693 | - m->cfg.extra_header_text_ += "\n"; | |
| 726 | + m->cfg.extra_header_text(text); | |
| 727 | +} | |
| 728 | + | |
| 729 | +Config& | |
| 730 | +Config::extra_header_text(std::string const& val) | |
| 731 | +{ | |
| 732 | + extra_header_text_ = val; | |
| 733 | + if (!extra_header_text_.empty() && extra_header_text_.back() != '\n') { | |
| 734 | + extra_header_text_ += "\n"; | |
| 694 | 735 | } else { |
| 695 | 736 | QTC::TC("qpdf", "QPDFWriter extra header text no newline"); |
| 696 | 737 | } |
| 738 | + return *this; | |
| 697 | 739 | } |
| 698 | 740 | |
| 699 | 741 | void |
| 700 | 742 | QPDFWriter::setStaticID(bool val) |
| 701 | 743 | { |
| 702 | - m->cfg.static_id_ = val; | |
| 744 | + m->cfg.static_id(val); | |
| 703 | 745 | } |
| 704 | 746 | |
| 705 | 747 | void |
| 706 | 748 | QPDFWriter::setDeterministicID(bool val) |
| 707 | 749 | { |
| 708 | - m->cfg.deterministic_id_ = val; | |
| 750 | + m->cfg.deterministic_id(val); | |
| 709 | 751 | } |
| 710 | 752 | |
| 711 | 753 | void |
| ... | ... | @@ -719,37 +761,61 @@ QPDFWriter::setStaticAesIV(bool val) |
| 719 | 761 | void |
| 720 | 762 | QPDFWriter::setSuppressOriginalObjectIDs(bool val) |
| 721 | 763 | { |
| 722 | - m->cfg.suppress_original_object_ids_ = val; | |
| 764 | + m->cfg.suppress_original_object_ids(val); | |
| 723 | 765 | } |
| 724 | 766 | |
| 725 | 767 | void |
| 726 | 768 | QPDFWriter::setPreserveEncryption(bool val) |
| 727 | 769 | { |
| 728 | - m->cfg.preserve_encryption_ = val; | |
| 770 | + m->cfg.preserve_encryption(val); | |
| 729 | 771 | } |
| 730 | 772 | |
| 731 | 773 | void |
| 732 | 774 | QPDFWriter::setLinearization(bool val) |
| 733 | 775 | { |
| 734 | - m->cfg.linearized_ = val; | |
| 735 | - if (val) { | |
| 736 | - m->cfg.pclm_ = false; | |
| 776 | + m->cfg.linearize(val); | |
| 777 | +} | |
| 778 | + | |
| 779 | +Config& | |
| 780 | +Config::linearize(bool val) | |
| 781 | +{ | |
| 782 | + if (pclm_ || qdf_) { | |
| 783 | + usage("linearize cannot be set when qdf or pclm are set"); | |
| 784 | + return *this; | |
| 737 | 785 | } |
| 786 | + linearize_ = val; | |
| 787 | + return *this; | |
| 738 | 788 | } |
| 739 | 789 | |
| 740 | 790 | void |
| 741 | 791 | QPDFWriter::setLinearizationPass1Filename(std::string const& filename) |
| 742 | 792 | { |
| 743 | - m->cfg.lin_pass1_filename_ = filename; | |
| 793 | + m->cfg.lin_pass1_filename(filename); | |
| 744 | 794 | } |
| 745 | 795 | |
| 746 | 796 | void |
| 747 | 797 | QPDFWriter::setPCLm(bool val) |
| 748 | 798 | { |
| 749 | - m->cfg.pclm_ = val; | |
| 799 | + m->cfg.pclm(val); | |
| 800 | +} | |
| 801 | + | |
| 802 | +Config& | |
| 803 | +Config::pclm(bool val) | |
| 804 | +{ | |
| 805 | + if (stream_decode_level_set_ || compress_streams_set_ || linearize_) { | |
| 806 | + usage( | |
| 807 | + "pclm cannot be set when stream_decode_level, compress_streams, linearize or qdf are " | |
| 808 | + "set"); | |
| 809 | + return *this; | |
| 810 | + } | |
| 811 | + pclm_ = val; | |
| 750 | 812 | if (val) { |
| 751 | - m->cfg.linearized_ = false; | |
| 813 | + stream_decode_level_ = qpdf_dl_none; | |
| 814 | + compress_streams_ = false; | |
| 815 | + linearize_ = false; | |
| 752 | 816 | } |
| 817 | + | |
| 818 | + return *this; | |
| 753 | 819 | } |
| 754 | 820 | |
| 755 | 821 | void |
| ... | ... | @@ -817,7 +883,7 @@ QPDFWriter::setR4EncryptionParametersInsecure( |
| 817 | 883 | bool use_aes) |
| 818 | 884 | { |
| 819 | 885 | m->encryption = std::make_unique<Encryption>(4, 4, 16, encrypt_metadata); |
| 820 | - m->cfg.encrypt_use_aes_ = use_aes; | |
| 886 | + m->cfg.encrypt_use_aes(use_aes); | |
| 821 | 887 | m->interpretR3EncryptionParameters( |
| 822 | 888 | allow_accessibility, |
| 823 | 889 | allow_extract, |
| ... | ... | @@ -844,7 +910,7 @@ QPDFWriter::setR5EncryptionParameters( |
| 844 | 910 | bool encrypt_metadata) |
| 845 | 911 | { |
| 846 | 912 | m->encryption = std::make_unique<Encryption>(5, 5, 32, encrypt_metadata); |
| 847 | - m->cfg.encrypt_use_aes_ = true; | |
| 913 | + m->cfg.encrypt_use_aes(true); | |
| 848 | 914 | m->interpretR3EncryptionParameters( |
| 849 | 915 | allow_accessibility, |
| 850 | 916 | allow_extract, |
| ... | ... | @@ -880,7 +946,7 @@ QPDFWriter::setR6EncryptionParameters( |
| 880 | 946 | allow_modify_other, |
| 881 | 947 | print, |
| 882 | 948 | qpdf_r3m_all); |
| 883 | - m->cfg.encrypt_use_aes_ = true; | |
| 949 | + m->cfg.encrypt_use_aes(true); | |
| 884 | 950 | m->setEncryptionParameters(user_password, owner_password); |
| 885 | 951 | } |
| 886 | 952 | |
| ... | ... | @@ -1001,7 +1067,7 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) |
| 1001 | 1067 | void |
| 1002 | 1068 | impl::Writer::copyEncryptionParameters(QPDF& qpdf) |
| 1003 | 1069 | { |
| 1004 | - cfg.preserve_encryption_ = false; | |
| 1070 | + cfg.preserve_encryption(false); | |
| 1005 | 1071 | QPDFObjectHandle trailer = qpdf.getTrailer(); |
| 1006 | 1072 | if (trailer.hasKey("/Encrypt")) { |
| 1007 | 1073 | generateID(true); |
| ... | ... | @@ -1021,10 +1087,10 @@ impl::Writer::copyEncryptionParameters(QPDF& qpdf) |
| 1021 | 1087 | // Acrobat doesn't create files with V >= 4 that don't use AES, and the logic of |
| 1022 | 1088 | // figuring out whether AES is used or not is complicated with /StmF, /StrF, and /EFF |
| 1023 | 1089 | // all potentially having different values. |
| 1024 | - cfg.encrypt_use_aes_ = true; | |
| 1090 | + cfg.encrypt_use_aes(true); | |
| 1025 | 1091 | } |
| 1026 | 1092 | QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", encrypt_metadata ? 0 : 1); |
| 1027 | - QTC::TC("qpdf", "QPDFWriter copy use_aes", cfg.encrypt_use_aes_ ? 0 : 1); | |
| 1093 | + QTC::TC("qpdf", "QPDFWriter copy use_aes", cfg.encrypt_use_aes() ? 0 : 1); | |
| 1028 | 1094 | |
| 1029 | 1095 | encryption = std::make_unique<Encryption>( |
| 1030 | 1096 | V, |
| ... | ... | @@ -1065,7 +1131,7 @@ impl::Writer::disableIncompatibleEncryption(int major, int minor, int extension_ |
| 1065 | 1131 | encryption = nullptr; |
| 1066 | 1132 | } |
| 1067 | 1133 | } else if (compareVersions(major, minor, 1, 6) < 0) { |
| 1068 | - if (cfg.encrypt_use_aes_) { | |
| 1134 | + if (cfg.encrypt_use_aes()) { | |
| 1069 | 1135 | encryption = nullptr; |
| 1070 | 1136 | } |
| 1071 | 1137 | } else if ( |
| ... | ... | @@ -1122,7 +1188,7 @@ impl::Writer::setEncryptionMinimumVersion() |
| 1122 | 1188 | } else if (R == 5) { |
| 1123 | 1189 | setMinimumPDFVersion("1.7", 3); |
| 1124 | 1190 | } else if (R == 4) { |
| 1125 | - setMinimumPDFVersion(cfg.encrypt_use_aes_ ? "1.6" : "1.5"); | |
| 1191 | + setMinimumPDFVersion(cfg.encrypt_use_aes() ? "1.6" : "1.5"); | |
| 1126 | 1192 | } else if (R == 3) { |
| 1127 | 1193 | setMinimumPDFVersion("1.4"); |
| 1128 | 1194 | } else { |
| ... | ... | @@ -1135,7 +1201,12 @@ impl::Writer::setDataKey(int objid) |
| 1135 | 1201 | { |
| 1136 | 1202 | if (encryption) { |
| 1137 | 1203 | cur_data_key = QPDF::compute_data_key( |
| 1138 | - encryption_key, objid, 0, cfg.encrypt_use_aes_, encryption->getV(), encryption->getR()); | |
| 1204 | + encryption_key, | |
| 1205 | + objid, | |
| 1206 | + 0, | |
| 1207 | + cfg.encrypt_use_aes(), | |
| 1208 | + encryption->getV(), | |
| 1209 | + encryption->getR()); | |
| 1139 | 1210 | } |
| 1140 | 1211 | } |
| 1141 | 1212 | |
| ... | ... | @@ -1203,7 +1274,7 @@ template <typename... Args> |
| 1203 | 1274 | impl::Writer& |
| 1204 | 1275 | impl::Writer::write_qdf(Args&&... args) |
| 1205 | 1276 | { |
| 1206 | - if (cfg.qdf_mode_) { | |
| 1277 | + if (cfg.qdf()) { | |
| 1207 | 1278 | pipeline->write(std::forward<Args>(args)...); |
| 1208 | 1279 | } |
| 1209 | 1280 | return *this; |
| ... | ... | @@ -1213,7 +1284,7 @@ template <typename... Args> |
| 1213 | 1284 | impl::Writer& |
| 1214 | 1285 | impl::Writer::write_no_qdf(Args&&... args) |
| 1215 | 1286 | { |
| 1216 | - if (!cfg.qdf_mode_) { | |
| 1287 | + if (!cfg.qdf()) { | |
| 1217 | 1288 | pipeline->write(std::forward<Args>(args)...); |
| 1218 | 1289 | } |
| 1219 | 1290 | return *this; |
| ... | ... | @@ -1222,7 +1293,7 @@ impl::Writer::write_no_qdf(Args&&... args) |
| 1222 | 1293 | void |
| 1223 | 1294 | impl::Writer::adjustAESStreamLength(size_t& length) |
| 1224 | 1295 | { |
| 1225 | - if (encryption && !cur_data_key.empty() && cfg.encrypt_use_aes_) { | |
| 1296 | + if (encryption && !cur_data_key.empty() && cfg.encrypt_use_aes()) { | |
| 1226 | 1297 | // Stream length will be padded with 1 to 16 bytes to end up as a multiple of 16. It will |
| 1227 | 1298 | // also be prepended by 16 bits of random data. |
| 1228 | 1299 | length += 32 - (length & 0xf); |
| ... | ... | @@ -1234,7 +1305,7 @@ impl::Writer::write_encrypted(std::string_view str) |
| 1234 | 1305 | { |
| 1235 | 1306 | if (!(encryption && !cur_data_key.empty())) { |
| 1236 | 1307 | write(str); |
| 1237 | - } else if (cfg.encrypt_use_aes_) { | |
| 1308 | + } else if (cfg.encrypt_use_aes()) { | |
| 1238 | 1309 | write(pl::pipe<Pl_AES_PDF>(str, true, cur_data_key)); |
| 1239 | 1310 | } else { |
| 1240 | 1311 | write(pl::pipe<Pl_RC4>(str, cur_data_key)); |
| ... | ... | @@ -1305,7 +1376,7 @@ impl::Writer::enqueue(QPDFObjectHandle const& object) |
| 1305 | 1376 | "Use QPDF::copyForeignObject to add objects from another file." // |
| 1306 | 1377 | ); |
| 1307 | 1378 | |
| 1308 | - if (cfg.qdf_mode_ && object.isStreamOfType("/XRef")) { | |
| 1379 | + if (cfg.qdf() && object.isStreamOfType("/XRef")) { | |
| 1309 | 1380 | // As a special case, do not output any extraneous XRef streams in QDF mode. Doing so |
| 1310 | 1381 | // will confuse fix-qdf, which expects to see only one XRef stream at the end of the |
| 1311 | 1382 | // file. This case can occur when creating a QDF from a file with object streams when |
| ... | ... | @@ -1331,10 +1402,10 @@ impl::Writer::enqueue(QPDFObjectHandle const& object) |
| 1331 | 1402 | if (og.getGen() == 0 && object_stream_to_objects.contains(og.getObj())) { |
| 1332 | 1403 | // For linearized files, uncompressed objects go at end, and we take care of |
| 1333 | 1404 | // assigning numbers to them elsewhere. |
| 1334 | - if (!cfg.linearized_) { | |
| 1405 | + if (!cfg.linearize()) { | |
| 1335 | 1406 | assignCompressedObjectNumbers(og); |
| 1336 | 1407 | } |
| 1337 | - } else if (!cfg.direct_stream_lengths_ && object.isStream()) { | |
| 1408 | + } else if (!cfg.direct_stream_lengths() && object.isStream()) { | |
| 1338 | 1409 | // reserve next object ID for length |
| 1339 | 1410 | ++next_objid; |
| 1340 | 1411 | } |
| ... | ... | @@ -1343,7 +1414,7 @@ impl::Writer::enqueue(QPDFObjectHandle const& object) |
| 1343 | 1414 | return; |
| 1344 | 1415 | } |
| 1345 | 1416 | |
| 1346 | - if (cfg.linearized_) { | |
| 1417 | + if (cfg.linearize()) { | |
| 1347 | 1418 | return; |
| 1348 | 1419 | } |
| 1349 | 1420 | |
| ... | ... | @@ -1364,7 +1435,7 @@ impl::Writer::enqueue(QPDFObjectHandle const& object) |
| 1364 | 1435 | void |
| 1365 | 1436 | impl::Writer::unparseChild(QPDFObjectHandle const& child, size_t level, int flags) |
| 1366 | 1437 | { |
| 1367 | - if (!cfg.linearized_) { | |
| 1438 | + if (!cfg.linearize()) { | |
| 1368 | 1439 | enqueue(child); |
| 1369 | 1440 | } |
| 1370 | 1441 | if (child.indirect()) { |
| ... | ... | @@ -1423,7 +1494,7 @@ impl::Writer::writeTrailer( |
| 1423 | 1494 | } |
| 1424 | 1495 | write("<00000000000000000000000000000000>"); |
| 1425 | 1496 | } else { |
| 1426 | - if (linearization_pass == 0 && cfg.deterministic_id_) { | |
| 1497 | + if (linearization_pass == 0 && cfg.deterministic_id()) { | |
| 1427 | 1498 | computeDeterministicIDData(); |
| 1428 | 1499 | } |
| 1429 | 1500 | generateID(encryption.get()); |
| ... | ... | @@ -1454,19 +1525,19 @@ impl::Writer::will_filter_stream(QPDFObjectHandle stream, std::string* stream_da |
| 1454 | 1525 | { |
| 1455 | 1526 | const bool is_root_metadata = stream.isRootMetadata(); |
| 1456 | 1527 | bool filter = false; |
| 1457 | - auto decode_level = cfg.stream_decode_level_; | |
| 1528 | + auto decode_level = cfg.stream_decode_level(); | |
| 1458 | 1529 | int encode_flags = 0; |
| 1459 | 1530 | Dictionary stream_dict = stream.getDict(); |
| 1460 | 1531 | |
| 1461 | 1532 | if (stream.getFilterOnWrite()) { |
| 1462 | - filter = stream.isDataModified() || cfg.compress_streams_ || decode_level != qpdf_dl_none; | |
| 1463 | - if (cfg.compress_streams_) { | |
| 1533 | + filter = stream.isDataModified() || cfg.compress_streams() || decode_level != qpdf_dl_none; | |
| 1534 | + if (cfg.compress_streams()) { | |
| 1464 | 1535 | // Don't filter if the stream is already compressed with FlateDecode. This way we don't |
| 1465 | 1536 | // make it worse if the original file used a better Flate algorithm, and we don't spend |
| 1466 | 1537 | // time and CPU cycles uncompressing and recompressing stuff. This can be overridden |
| 1467 | 1538 | // with setRecompressFlate(true). |
| 1468 | 1539 | Name Filter = stream_dict["/Filter"]; |
| 1469 | - if (Filter && !cfg.recompress_flate_ && !stream.isDataModified() && | |
| 1540 | + if (Filter && !cfg.recompress_flate() && !stream.isDataModified() && | |
| 1470 | 1541 | (Filter == "/FlateDecode" || Filter == "/Fl")) { |
| 1471 | 1542 | filter = false; |
| 1472 | 1543 | } |
| ... | ... | @@ -1474,10 +1545,10 @@ impl::Writer::will_filter_stream(QPDFObjectHandle stream, std::string* stream_da |
| 1474 | 1545 | if (is_root_metadata && (!encryption || !encryption->getEncryptMetadata())) { |
| 1475 | 1546 | filter = true; |
| 1476 | 1547 | decode_level = qpdf_dl_all; |
| 1477 | - } else if (cfg.normalize_content_ && normalized_streams.contains(stream)) { | |
| 1548 | + } else if (cfg.normalize_content() && normalized_streams.contains(stream)) { | |
| 1478 | 1549 | encode_flags = qpdf_ef_normalize; |
| 1479 | 1550 | filter = true; |
| 1480 | - } else if (filter && cfg.compress_streams_) { | |
| 1551 | + } else if (filter && cfg.compress_streams()) { | |
| 1481 | 1552 | encode_flags = qpdf_ef_compress; |
| 1482 | 1553 | } |
| 1483 | 1554 | } |
| ... | ... | @@ -1531,11 +1602,11 @@ impl::Writer::unparseObject( |
| 1531 | 1602 | // For non-qdf, "indent" and "indent_large" are a single space between tokens. For qdf, they |
| 1532 | 1603 | // include the preceding newline. |
| 1533 | 1604 | std::string indent_large = " "; |
| 1534 | - if (cfg.qdf_mode_) { | |
| 1605 | + if (cfg.qdf()) { | |
| 1535 | 1606 | indent_large.append(2 * (level + 1), ' '); |
| 1536 | 1607 | indent_large[0] = '\n'; |
| 1537 | 1608 | } |
| 1538 | - std::string_view indent{indent_large.data(), cfg.qdf_mode_ ? indent_large.size() - 2 : 1}; | |
| 1609 | + std::string_view indent{indent_large.data(), cfg.qdf() ? indent_large.size() - 2 : 1}; | |
| 1539 | 1610 | |
| 1540 | 1611 | if (auto const tc = object.getTypeCode(); tc == ::ot_array) { |
| 1541 | 1612 | // Note: PDF spec 1.4 implementation note 121 states that Acrobat requires a space after the |
| ... | ... | @@ -1591,7 +1662,7 @@ impl::Writer::unparseObject( |
| 1591 | 1662 | if (need_extensions_adbe) { |
| 1592 | 1663 | if (!(have_extensions_other || have_extensions_adbe)) { |
| 1593 | 1664 | // We need Extensions and don't have it. Create it here. |
| 1594 | - QTC::TC("qpdf", "QPDFWriter create Extensions", cfg.qdf_mode_ ? 0 : 1); | |
| 1665 | + QTC::TC("qpdf", "QPDFWriter create Extensions", cfg.qdf() ? 0 : 1); | |
| 1595 | 1666 | extensions = object.replaceKeyAndGetNew( |
| 1596 | 1667 | "/Extensions", QPDFObjectHandle::newDictionary()); |
| 1597 | 1668 | } |
| ... | ... | @@ -1696,7 +1767,7 @@ impl::Writer::unparseObject( |
| 1696 | 1767 | if (flags & f_stream) { |
| 1697 | 1768 | write(indent_large).write("/Length "); |
| 1698 | 1769 | |
| 1699 | - if (cfg.direct_stream_lengths_) { | |
| 1770 | + if (cfg.direct_stream_lengths()) { | |
| 1700 | 1771 | write(stream_length); |
| 1701 | 1772 | } else { |
| 1702 | 1773 | write(cur_stream_length_id).write(" 0 R"); |
| ... | ... | @@ -1709,7 +1780,7 @@ impl::Writer::unparseObject( |
| 1709 | 1780 | write(indent).write(">>"); |
| 1710 | 1781 | } else if (tc == ::ot_stream) { |
| 1711 | 1782 | // Write stream data to a buffer. |
| 1712 | - if (!cfg.direct_stream_lengths_) { | |
| 1783 | + if (!cfg.direct_stream_lengths()) { | |
| 1713 | 1784 | cur_stream_length_id = obj[old_og].renumber + 1; |
| 1714 | 1785 | } |
| 1715 | 1786 | |
| ... | ... | @@ -1730,14 +1801,14 @@ impl::Writer::unparseObject( |
| 1730 | 1801 | unparseObject(stream_dict, 0, flags, cur_stream_length, compress_stream); |
| 1731 | 1802 | char last_char = stream_data.empty() ? '\0' : stream_data.back(); |
| 1732 | 1803 | write("\nstream\n").write_encrypted(stream_data); |
| 1733 | - added_newline = cfg.newline_before_endstream_ || (cfg.qdf_mode_ && last_char != '\n'); | |
| 1804 | + added_newline = cfg.newline_before_endstream() || (cfg.qdf() && last_char != '\n'); | |
| 1734 | 1805 | write(added_newline ? "\nendstream" : "endstream"); |
| 1735 | 1806 | } else if (tc == ::ot_string) { |
| 1736 | 1807 | std::string val; |
| 1737 | 1808 | if (encryption && !(flags & f_in_ostream) && !(flags & f_no_encryption) && |
| 1738 | 1809 | !cur_data_key.empty()) { |
| 1739 | 1810 | val = object.getStringValue(); |
| 1740 | - if (cfg.encrypt_use_aes_) { | |
| 1811 | + if (cfg.encrypt_use_aes()) { | |
| 1741 | 1812 | Pl_Buffer bufpl("encrypted string"); |
| 1742 | 1813 | Pl_AES_PDF pl("aes encrypt string", &bufpl, true, cur_data_key); |
| 1743 | 1814 | pl.writeString(val); |
| ... | ... | @@ -1803,7 +1874,7 @@ impl::Writer::writeObjectStream(QPDFObjectHandle object) |
| 1803 | 1874 | std::string stream_buffer_pass1; |
| 1804 | 1875 | std::string stream_buffer_pass2; |
| 1805 | 1876 | int first_obj = -1; |
| 1806 | - const bool compressed = cfg.compress_streams_ && !cfg.qdf_mode_; | |
| 1877 | + const bool compressed = cfg.compress_streams() && !cfg.qdf(); | |
| 1807 | 1878 | { |
| 1808 | 1879 | // Pass 1 |
| 1809 | 1880 | auto pp_ostream_pass1 = pipeline_stack.activate(stream_buffer_pass1); |
| ... | ... | @@ -1815,9 +1886,9 @@ impl::Writer::writeObjectStream(QPDFObjectHandle object) |
| 1815 | 1886 | if (first_obj == -1) { |
| 1816 | 1887 | first_obj = new_o; |
| 1817 | 1888 | } |
| 1818 | - if (cfg.qdf_mode_) { | |
| 1889 | + if (cfg.qdf()) { | |
| 1819 | 1890 | write("%% Object stream: object ").write(new_o).write(", index ").write(count); |
| 1820 | - if (!cfg.suppress_original_object_ids_) { | |
| 1891 | + if (!cfg.suppress_original_object_ids()) { | |
| 1821 | 1892 | write("; original object ID: ").write(og.getObj()); |
| 1822 | 1893 | // For compatibility, only write the generation if non-zero. While object |
| 1823 | 1894 | // streams only allow objects with generation 0, if we are generating object |
| ... | ... | @@ -1893,11 +1964,10 @@ impl::Writer::writeObjectStream(QPDFObjectHandle object) |
| 1893 | 1964 | } |
| 1894 | 1965 | } |
| 1895 | 1966 | write_qdf("\n").write_no_qdf(" ").write(">>\nstream\n").write_encrypted(stream_buffer_pass2); |
| 1967 | + write(cfg.newline_before_endstream() ? "\nendstream" : "endstream"); | |
| 1896 | 1968 | if (encryption) { |
| 1897 | - QTC::TC("qpdf", "QPDFWriter encrypt object stream"); | |
| 1969 | + cur_data_key.clear(); | |
| 1898 | 1970 | } |
| 1899 | - write(cfg.newline_before_endstream_ ? "\nendstream" : "endstream"); | |
| 1900 | - cur_data_key.clear(); | |
| 1901 | 1971 | closeObject(new_stream_id); |
| 1902 | 1972 | } |
| 1903 | 1973 | |
| ... | ... | @@ -1914,7 +1984,7 @@ impl::Writer::writeObject(QPDFObjectHandle object, int object_stream_index) |
| 1914 | 1984 | |
| 1915 | 1985 | indicateProgress(false, false); |
| 1916 | 1986 | auto new_id = obj[old_og].renumber; |
| 1917 | - if (cfg.qdf_mode_) { | |
| 1987 | + if (cfg.qdf()) { | |
| 1918 | 1988 | if (page_object_to_seq.contains(old_og)) { |
| 1919 | 1989 | write("%% Page ").write(page_object_to_seq[old_og]).write("\n"); |
| 1920 | 1990 | } |
| ... | ... | @@ -1923,7 +1993,7 @@ impl::Writer::writeObject(QPDFObjectHandle object, int object_stream_index) |
| 1923 | 1993 | } |
| 1924 | 1994 | } |
| 1925 | 1995 | if (object_stream_index == -1) { |
| 1926 | - if (cfg.qdf_mode_ && !cfg.suppress_original_object_ids_) { | |
| 1996 | + if (cfg.qdf() && !cfg.suppress_original_object_ids()) { | |
| 1927 | 1997 | write("%% Original object ID: ").write(object.getObjGen().unparse(' ')).write("\n"); |
| 1928 | 1998 | } |
| 1929 | 1999 | openObject(new_id); |
| ... | ... | @@ -1936,8 +2006,8 @@ impl::Writer::writeObject(QPDFObjectHandle object, int object_stream_index) |
| 1936 | 2006 | write("\n"); |
| 1937 | 2007 | } |
| 1938 | 2008 | |
| 1939 | - if (!cfg.direct_stream_lengths_ && object.isStream()) { | |
| 1940 | - if (cfg.qdf_mode_) { | |
| 2009 | + if (!cfg.direct_stream_lengths() && object.isStream()) { | |
| 2010 | + if (cfg.qdf()) { | |
| 1941 | 2011 | if (added_newline) { |
| 1942 | 2012 | write("%QDF: ignore_newline\n"); |
| 1943 | 2013 | } |
| ... | ... | @@ -1973,7 +2043,7 @@ impl::Writer::generateID(bool encrypted) |
| 1973 | 2043 | |
| 1974 | 2044 | std::string result; |
| 1975 | 2045 | |
| 1976 | - if (cfg.static_id_) { | |
| 2046 | + if (cfg.static_id()) { | |
| 1977 | 2047 | // For test suite use only... |
| 1978 | 2048 | static unsigned char tmp[] = { |
| 1979 | 2049 | 0x31, |
| ... | ... | @@ -2005,7 +2075,7 @@ impl::Writer::generateID(bool encrypted) |
| 2005 | 2075 | // that case, would have the same ID regardless of the output file's name. |
| 2006 | 2076 | |
| 2007 | 2077 | std::string seed; |
| 2008 | - if (cfg.deterministic_id_) { | |
| 2078 | + if (cfg.deterministic_id()) { | |
| 2009 | 2079 | if (encrypted) { |
| 2010 | 2080 | throw std::runtime_error( |
| 2011 | 2081 | "QPDFWriter: unable to generated a deterministic ID because the file to be " |
| ... | ... | @@ -2087,7 +2157,7 @@ impl::Writer::preserveObjectStreams() |
| 2087 | 2157 | // objects from being included. |
| 2088 | 2158 | auto end = xref.cend(); |
| 2089 | 2159 | obj.streams_empty = true; |
| 2090 | - if (cfg.preserve_unreferenced_objects_) { | |
| 2160 | + if (cfg.preserve_unreferenced()) { | |
| 2091 | 2161 | for (auto iter = xref.cbegin(); iter != end; ++iter) { |
| 2092 | 2162 | if (iter->second.getType() == 2) { |
| 2093 | 2163 | // Pdf contains object streams. |
| ... | ... | @@ -2229,63 +2299,61 @@ impl::Writer::doWriteSetup() |
| 2229 | 2299 | |
| 2230 | 2300 | // Do preliminary setup |
| 2231 | 2301 | |
| 2232 | - if (cfg.linearized_) { | |
| 2233 | - cfg.qdf_mode_ = false; | |
| 2302 | + if (cfg.linearize()) { | |
| 2303 | + cfg.qdf(false); | |
| 2234 | 2304 | } |
| 2235 | 2305 | |
| 2236 | - if (cfg.pclm_) { | |
| 2237 | - cfg.stream_decode_level_ = qpdf_dl_none; | |
| 2238 | - cfg.compress_streams_ = false; | |
| 2306 | + if (cfg.pclm()) { | |
| 2239 | 2307 | encryption = nullptr; |
| 2240 | 2308 | } |
| 2241 | 2309 | |
| 2242 | - if (cfg.qdf_mode_) { | |
| 2310 | + if (cfg.qdf()) { | |
| 2243 | 2311 | if (!cfg.normalize_content_set_) { |
| 2244 | - cfg.normalize_content_ = true; | |
| 2312 | + cfg.normalize_content(true); | |
| 2245 | 2313 | } |
| 2246 | 2314 | if (!cfg.compress_streams_set_) { |
| 2247 | - cfg.compress_streams_ = false; | |
| 2315 | + cfg.compress_streams(false); | |
| 2248 | 2316 | } |
| 2249 | 2317 | if (!cfg.stream_decode_level_set_) { |
| 2250 | - cfg.stream_decode_level_ = qpdf_dl_generalized; | |
| 2318 | + cfg.stream_decode_level(qpdf_dl_generalized); | |
| 2251 | 2319 | } |
| 2252 | 2320 | } |
| 2253 | 2321 | |
| 2254 | 2322 | if (encryption) { |
| 2255 | 2323 | // Encryption has been explicitly set |
| 2256 | - cfg.preserve_encryption_ = false; | |
| 2257 | - } else if (cfg.normalize_content_ || cfg.pclm_ || cfg.qdf_mode_) { | |
| 2324 | + cfg.preserve_encryption(false); | |
| 2325 | + } else if (cfg.normalize_content() || cfg.pclm() || cfg.qdf()) { | |
| 2258 | 2326 | // Encryption makes looking at contents pretty useless. If the user explicitly encrypted |
| 2259 | 2327 | // though, we still obey that. |
| 2260 | - cfg.preserve_encryption_ = false; | |
| 2328 | + cfg.preserve_encryption(false); | |
| 2261 | 2329 | } |
| 2262 | 2330 | |
| 2263 | - if (cfg.preserve_encryption_) { | |
| 2331 | + if (cfg.preserve_encryption()) { | |
| 2264 | 2332 | copyEncryptionParameters(qpdf); |
| 2265 | 2333 | } |
| 2266 | 2334 | |
| 2267 | - if (!cfg.forced_pdf_version_.empty()) { | |
| 2335 | + if (!cfg.forced_pdf_version().empty()) { | |
| 2268 | 2336 | int major = 0; |
| 2269 | 2337 | int minor = 0; |
| 2270 | - parseVersion(cfg.forced_pdf_version_, major, minor); | |
| 2271 | - disableIncompatibleEncryption(major, minor, cfg.forced_extension_level_); | |
| 2338 | + parseVersion(cfg.forced_pdf_version(), major, minor); | |
| 2339 | + disableIncompatibleEncryption(major, minor, cfg.forced_extension_level()); | |
| 2272 | 2340 | if (compareVersions(major, minor, 1, 5) < 0) { |
| 2273 | - cfg.object_stream_mode_ = qpdf_o_disable; | |
| 2341 | + cfg.object_streams(qpdf_o_disable); | |
| 2274 | 2342 | } |
| 2275 | 2343 | } |
| 2276 | 2344 | |
| 2277 | - if (cfg.qdf_mode_ || cfg.normalize_content_) { | |
| 2345 | + if (cfg.qdf() || cfg.normalize_content()) { | |
| 2278 | 2346 | initializeSpecialStreams(); |
| 2279 | 2347 | } |
| 2280 | 2348 | |
| 2281 | - if (cfg.qdf_mode_) { | |
| 2349 | + if (cfg.qdf()) { | |
| 2282 | 2350 | // Generate indirect stream lengths for qdf mode since fix-qdf uses them for storing |
| 2283 | 2351 | // recomputed stream length data. Certain streams such as object streams, xref streams, and |
| 2284 | 2352 | // hint streams always get direct stream lengths. |
| 2285 | 2353 | cfg.direct_stream_lengths_ = false; |
| 2286 | 2354 | } |
| 2287 | 2355 | |
| 2288 | - switch (cfg.object_stream_mode_) { | |
| 2356 | + switch (cfg.object_streams()) { | |
| 2289 | 2357 | case qpdf_o_disable: |
| 2290 | 2358 | initializeTables(); |
| 2291 | 2359 | obj.streams_empty = true; |
| ... | ... | @@ -2299,12 +2367,10 @@ impl::Writer::doWriteSetup() |
| 2299 | 2367 | case qpdf_o_generate: |
| 2300 | 2368 | generateObjectStreams(); |
| 2301 | 2369 | break; |
| 2302 | - | |
| 2303 | - // no default so gcc will warn for missing case tag | |
| 2304 | 2370 | } |
| 2305 | 2371 | |
| 2306 | 2372 | if (!obj.streams_empty) { |
| 2307 | - if (cfg.linearized_) { | |
| 2373 | + if (cfg.linearize()) { | |
| 2308 | 2374 | // Page dictionaries are not allowed to be compressed objects. |
| 2309 | 2375 | for (auto& page: pages) { |
| 2310 | 2376 | if (obj[page].object_stream > 0) { |
| ... | ... | @@ -2313,7 +2379,7 @@ impl::Writer::doWriteSetup() |
| 2313 | 2379 | } |
| 2314 | 2380 | } |
| 2315 | 2381 | |
| 2316 | - if (cfg.linearized_ || encryption) { | |
| 2382 | + if (cfg.linearize() || encryption) { | |
| 2317 | 2383 | // The document catalog is not allowed to be compressed in cfg.linearized_ files either. |
| 2318 | 2384 | // It also appears that Adobe Reader 8.0.0 has a bug that prevents it from being able to |
| 2319 | 2385 | // handle encrypted files with compressed document catalogs, so we disable them in that |
| ... | ... | @@ -2345,9 +2411,9 @@ impl::Writer::doWriteSetup() |
| 2345 | 2411 | setMinimumPDFVersion(qpdf.getPDFVersion(), qpdf.getExtensionLevel()); |
| 2346 | 2412 | final_pdf_version = min_pdf_version; |
| 2347 | 2413 | final_extension_level = min_extension_level; |
| 2348 | - if (!cfg.forced_pdf_version_.empty()) { | |
| 2349 | - final_pdf_version = cfg.forced_pdf_version_; | |
| 2350 | - final_extension_level = cfg.forced_extension_level_; | |
| 2414 | + if (!cfg.forced_pdf_version().empty()) { | |
| 2415 | + final_pdf_version = cfg.forced_pdf_version(); | |
| 2416 | + final_extension_level = cfg.forced_extension_level(); | |
| 2351 | 2417 | } |
| 2352 | 2418 | } |
| 2353 | 2419 | |
| ... | ... | @@ -2364,11 +2430,11 @@ impl::Writer::write() |
| 2364 | 2430 | |
| 2365 | 2431 | // Set up progress reporting. For linearized files, we write two passes. events_expected is an |
| 2366 | 2432 | // approximation, but it's good enough for progress reporting, which is mostly a guess anyway. |
| 2367 | - events_expected = QIntC::to_int(qpdf.getObjectCount() * (cfg.linearized_ ? 2 : 1)); | |
| 2433 | + events_expected = QIntC::to_int(qpdf.getObjectCount() * (cfg.linearize() ? 2 : 1)); | |
| 2368 | 2434 | |
| 2369 | 2435 | prepareFileForWrite(); |
| 2370 | 2436 | |
| 2371 | - if (cfg.linearized_) { | |
| 2437 | + if (cfg.linearize()) { | |
| 2372 | 2438 | writeLinearized(); |
| 2373 | 2439 | } else { |
| 2374 | 2440 | writeStandard(); |
| ... | ... | @@ -2430,7 +2496,7 @@ impl::Writer::writeEncryptionDictionary() |
| 2430 | 2496 | write("<<"); |
| 2431 | 2497 | if (V >= 4) { |
| 2432 | 2498 | write(" /CF << /StdCF << /AuthEvent /DocOpen /CFM "); |
| 2433 | - write(cfg.encrypt_use_aes_ ? (V < 5 ? "/AESV2" : "/AESV3") : "/V2"); | |
| 2499 | + write(cfg.encrypt_use_aes() ? (V < 5 ? "/AESV2" : "/AESV3") : "/V2"); | |
| 2434 | 2500 | // The PDF spec says the /Length key is optional, but the PDF previewer on some versions of |
| 2435 | 2501 | // MacOS won't open encrypted files without it. |
| 2436 | 2502 | write(V < 5 ? " /Length 16 >> >>" : " /Length 32 >> >>"); |
| ... | ... | @@ -2471,7 +2537,7 @@ void |
| 2471 | 2537 | impl::Writer::writeHeader() |
| 2472 | 2538 | { |
| 2473 | 2539 | write("%PDF-").write(final_pdf_version); |
| 2474 | - if (cfg.pclm_) { | |
| 2540 | + if (cfg.pclm()) { | |
| 2475 | 2541 | // PCLm version |
| 2476 | 2542 | write("\n%PCLm 1.0\n"); |
| 2477 | 2543 | } else { |
| ... | ... | @@ -2493,7 +2559,7 @@ impl::Writer::writeHintStream(int hint_id) |
| 2493 | 2559 | std::string hint_buffer; |
| 2494 | 2560 | int S = 0; |
| 2495 | 2561 | int O = 0; |
| 2496 | - bool compressed = cfg.compress_streams_; | |
| 2562 | + bool compressed = cfg.compress_streams(); | |
| 2497 | 2563 | lin.generateHintStream(new_obj, obj, hint_buffer, S, O, compressed); |
| 2498 | 2564 | |
| 2499 | 2565 | openObject(hint_id); |
| ... | ... | @@ -2606,7 +2672,7 @@ impl::Writer::writeXRefStream( |
| 2606 | 2672 | new_obj[xref_id].xref = QPDFXRefEntry(pipeline->getCount()); |
| 2607 | 2673 | |
| 2608 | 2674 | std::string xref_data; |
| 2609 | - const bool compressed = cfg.compress_streams_ && !cfg.qdf_mode_; | |
| 2675 | + const bool compressed = cfg.compress_streams() && !cfg.qdf(); | |
| 2610 | 2676 | { |
| 2611 | 2677 | auto pp_xref = pipeline_stack.activate(xref_data); |
| 2612 | 2678 | |
| ... | ... | @@ -2809,15 +2875,15 @@ impl::Writer::writeLinearized() |
| 2809 | 2875 | auto pp_md5 = pipeline_stack.popper(); |
| 2810 | 2876 | for (int pass: {1, 2}) { |
| 2811 | 2877 | if (pass == 1) { |
| 2812 | - if (!cfg.lin_pass1_filename_.empty()) { | |
| 2813 | - lin_pass1_file = QUtil::safe_fopen(cfg.lin_pass1_filename_.data(), "wb"); | |
| 2878 | + if (!cfg.lin_pass1_filename().empty()) { | |
| 2879 | + lin_pass1_file = QUtil::safe_fopen(cfg.lin_pass1_filename().data(), "wb"); | |
| 2814 | 2880 | pipeline_stack.activate( |
| 2815 | 2881 | pp_pass1, |
| 2816 | 2882 | std::make_unique<Pl_StdioFile>("linearization pass1", lin_pass1_file)); |
| 2817 | 2883 | } else { |
| 2818 | 2884 | pipeline_stack.activate(pp_pass1, true); |
| 2819 | 2885 | } |
| 2820 | - if (cfg.deterministic_id_) { | |
| 2886 | + if (cfg.deterministic_id()) { | |
| 2821 | 2887 | pipeline_stack.activate_md5(pp_md5); |
| 2822 | 2888 | } |
| 2823 | 2889 | } |
| ... | ... | @@ -2852,7 +2918,7 @@ impl::Writer::writeLinearized() |
| 2852 | 2918 | |
| 2853 | 2919 | // If the user supplied any additional header text, write it here after the linearization |
| 2854 | 2920 | // parameter dictionary. |
| 2855 | - write(cfg.extra_header_text_); | |
| 2921 | + write(cfg.extra_header_text()); | |
| 2856 | 2922 | |
| 2857 | 2923 | // Part 3: first page cross reference table and trailer. |
| 2858 | 2924 | |
| ... | ... | @@ -2987,7 +3053,7 @@ impl::Writer::writeLinearized() |
| 2987 | 3053 | write("startxref\n").write(first_xref_offset).write("\n%%EOF\n"); |
| 2988 | 3054 | |
| 2989 | 3055 | if (pass == 1) { |
| 2990 | - if (cfg.deterministic_id_) { | |
| 3056 | + if (cfg.deterministic_id()) { | |
| 2991 | 3057 | QTC::TC("qpdf", "QPDFWriter linearized deterministic ID", need_xref_stream ? 0 : 1); |
| 2992 | 3058 | computeDeterministicIDData(); |
| 2993 | 3059 | pp_md5.pop(); |
| ... | ... | @@ -3032,7 +3098,7 @@ impl::Writer::writeLinearized() |
| 3032 | 3098 | void |
| 3033 | 3099 | impl::Writer::enqueueObjectsStandard() |
| 3034 | 3100 | { |
| 3035 | - if (cfg.preserve_unreferenced_objects_) { | |
| 3101 | + if (cfg.preserve_unreferenced()) { | |
| 3036 | 3102 | for (auto const& oh: qpdf.getAllObjects()) { |
| 3037 | 3103 | enqueue(oh); |
| 3038 | 3104 | } |
| ... | ... | @@ -3113,16 +3179,16 @@ void |
| 3113 | 3179 | impl::Writer::writeStandard() |
| 3114 | 3180 | { |
| 3115 | 3181 | auto pp_md5 = pipeline_stack.popper(); |
| 3116 | - if (cfg.deterministic_id_) { | |
| 3182 | + if (cfg.deterministic_id()) { | |
| 3117 | 3183 | pipeline_stack.activate_md5(pp_md5); |
| 3118 | 3184 | } |
| 3119 | 3185 | |
| 3120 | 3186 | // Start writing |
| 3121 | 3187 | |
| 3122 | 3188 | writeHeader(); |
| 3123 | - write(cfg.extra_header_text_); | |
| 3189 | + write(cfg.extra_header_text()); | |
| 3124 | 3190 | |
| 3125 | - if (cfg.pclm_) { | |
| 3191 | + if (cfg.pclm()) { | |
| 3126 | 3192 | enqueueObjectsPCLm(); |
| 3127 | 3193 | } else { |
| 3128 | 3194 | enqueueObjectsStandard(); |
| ... | ... | @@ -3152,7 +3218,7 @@ impl::Writer::writeStandard() |
| 3152 | 3218 | } |
| 3153 | 3219 | write("startxref\n").write(xref_offset).write("\n%%EOF\n"); |
| 3154 | 3220 | |
| 3155 | - if (cfg.deterministic_id_) { | |
| 3221 | + if (cfg.deterministic_id()) { | |
| 3156 | 3222 | QTC::TC( |
| 3157 | 3223 | "qpdf", |
| 3158 | 3224 | "QPDFWriter standard deterministic ID", | ... | ... |
libqpdf/qpdf/QPDFWriter_private.hh
| ... | ... | @@ -23,14 +23,252 @@ namespace qpdf |
| 23 | 23 | class Config |
| 24 | 24 | { |
| 25 | 25 | friend class impl::Writer; |
| 26 | - friend class ::QPDFWriter; | |
| 26 | + | |
| 27 | + public: | |
| 28 | + bool | |
| 29 | + linearize() const | |
| 30 | + { | |
| 31 | + return linearize_; | |
| 32 | + } | |
| 33 | + | |
| 34 | + Config& linearize(bool val); | |
| 35 | + | |
| 36 | + std::string const& | |
| 37 | + lin_pass1_filename() const | |
| 38 | + { | |
| 39 | + return lin_pass1_filename_; | |
| 40 | + } | |
| 41 | + | |
| 42 | + Config& | |
| 43 | + lin_pass1_filename(std::string const& val) | |
| 44 | + { | |
| 45 | + lin_pass1_filename_ = val; | |
| 46 | + return *this; | |
| 47 | + } | |
| 48 | + | |
| 49 | + bool | |
| 50 | + preserve_encryption() const | |
| 51 | + { | |
| 52 | + return preserve_encryption_; | |
| 53 | + } | |
| 54 | + | |
| 55 | + Config& | |
| 56 | + preserve_encryption(bool val) | |
| 57 | + { | |
| 58 | + preserve_encryption_ = val; | |
| 59 | + return *this; | |
| 60 | + } | |
| 61 | + | |
| 62 | + bool | |
| 63 | + encrypt_use_aes() const | |
| 64 | + { | |
| 65 | + return encrypt_use_aes_; | |
| 66 | + } | |
| 67 | + | |
| 68 | + Config& | |
| 69 | + encrypt_use_aes(bool val) | |
| 70 | + { | |
| 71 | + encrypt_use_aes_ = val; | |
| 72 | + return *this; | |
| 73 | + } | |
| 74 | + | |
| 75 | + qpdf_stream_decode_level_e | |
| 76 | + stream_decode_level() const | |
| 77 | + { | |
| 78 | + return stream_decode_level_; | |
| 79 | + } | |
| 80 | + | |
| 81 | + Config& stream_decode_level(qpdf_stream_decode_level_e val); | |
| 82 | + | |
| 83 | + qpdf_object_stream_e | |
| 84 | + object_streams() const | |
| 85 | + { | |
| 86 | + return object_streams_; | |
| 87 | + } | |
| 88 | + | |
| 89 | + Config& | |
| 90 | + object_streams(qpdf_object_stream_e val) | |
| 91 | + { | |
| 92 | + object_streams_ = val; | |
| 93 | + return *this; | |
| 94 | + } | |
| 95 | + | |
| 96 | + bool | |
| 97 | + compress_streams() const | |
| 98 | + { | |
| 99 | + return compress_streams_; | |
| 100 | + } | |
| 101 | + | |
| 102 | + Config& compress_streams(bool val); | |
| 103 | + | |
| 104 | + bool | |
| 105 | + direct_stream_lengths() const | |
| 106 | + { | |
| 107 | + return direct_stream_lengths_; | |
| 108 | + } | |
| 109 | + | |
| 110 | + bool | |
| 111 | + newline_before_endstream() const | |
| 112 | + { | |
| 113 | + return newline_before_endstream_; | |
| 114 | + } | |
| 115 | + | |
| 116 | + Config& | |
| 117 | + newline_before_endstream(bool val) | |
| 118 | + { | |
| 119 | + newline_before_endstream_ = val; | |
| 120 | + return *this; | |
| 121 | + } | |
| 122 | + | |
| 123 | + bool | |
| 124 | + recompress_flate() const | |
| 125 | + { | |
| 126 | + return recompress_flate_; | |
| 127 | + } | |
| 128 | + | |
| 129 | + Config& | |
| 130 | + recompress_flate(bool val) | |
| 131 | + { | |
| 132 | + recompress_flate_ = val; | |
| 133 | + return *this; | |
| 134 | + } | |
| 135 | + | |
| 136 | + Config& stream_data(qpdf_stream_data_e val); | |
| 137 | + | |
| 138 | + std::string const& | |
| 139 | + forced_pdf_version() const | |
| 140 | + { | |
| 141 | + return forced_pdf_version_; | |
| 142 | + } | |
| 143 | + | |
| 144 | + Config& | |
| 145 | + forced_pdf_version(std::string const& val) | |
| 146 | + { | |
| 147 | + forced_pdf_version_ = val; | |
| 148 | + return *this; | |
| 149 | + } | |
| 150 | + | |
| 151 | + Config& | |
| 152 | + forced_pdf_version(std::string const& val, int ext) | |
| 153 | + { | |
| 154 | + forced_pdf_version_ = val; | |
| 155 | + forced_extension_level_ = ext; | |
| 156 | + return *this; | |
| 157 | + } | |
| 158 | + | |
| 159 | + int | |
| 160 | + forced_extension_level() const | |
| 161 | + { | |
| 162 | + return forced_extension_level_; | |
| 163 | + } | |
| 164 | + | |
| 165 | + Config& | |
| 166 | + forced_extension_level(int val) | |
| 167 | + { | |
| 168 | + forced_extension_level_ = val; | |
| 169 | + return *this; | |
| 170 | + } | |
| 171 | + | |
| 172 | + std::string const& | |
| 173 | + extra_header_text() | |
| 174 | + { | |
| 175 | + return extra_header_text_; | |
| 176 | + } | |
| 177 | + | |
| 178 | + Config& extra_header_text(std::string const& val); | |
| 179 | + | |
| 180 | + bool | |
| 181 | + preserve_unreferenced() const | |
| 182 | + { | |
| 183 | + return preserve_unreferenced_; | |
| 184 | + } | |
| 185 | + | |
| 186 | + Config& | |
| 187 | + preserve_unreferenced(bool val) | |
| 188 | + { | |
| 189 | + preserve_unreferenced_ = val; | |
| 190 | + return *this; | |
| 191 | + } | |
| 192 | + | |
| 193 | + bool | |
| 194 | + suppress_original_object_ids() const | |
| 195 | + { | |
| 196 | + return suppress_original_object_ids_; | |
| 197 | + } | |
| 198 | + | |
| 199 | + Config& | |
| 200 | + suppress_original_object_ids(bool val) | |
| 201 | + { | |
| 202 | + suppress_original_object_ids_ = val; | |
| 203 | + return *this; | |
| 204 | + } | |
| 205 | + | |
| 206 | + bool | |
| 207 | + qdf() const | |
| 208 | + { | |
| 209 | + return qdf_; | |
| 210 | + } | |
| 211 | + | |
| 212 | + Config& qdf(bool val); | |
| 213 | + | |
| 214 | + bool | |
| 215 | + normalize_content() const | |
| 216 | + { | |
| 217 | + return normalize_content_; | |
| 218 | + } | |
| 219 | + | |
| 220 | + Config& | |
| 221 | + normalize_content(bool val) | |
| 222 | + { | |
| 223 | + normalize_content_ = val; | |
| 224 | + normalize_content_set_ = true; | |
| 225 | + return *this; | |
| 226 | + } | |
| 227 | + | |
| 228 | + bool | |
| 229 | + deterministic_id() const | |
| 230 | + { | |
| 231 | + return deterministic_id_; | |
| 232 | + } | |
| 233 | + | |
| 234 | + Config& | |
| 235 | + deterministic_id(bool val) | |
| 236 | + { | |
| 237 | + deterministic_id_ = val; | |
| 238 | + return *this; | |
| 239 | + } | |
| 240 | + | |
| 241 | + bool | |
| 242 | + static_id() const | |
| 243 | + { | |
| 244 | + return static_id_; | |
| 245 | + } | |
| 246 | + | |
| 247 | + Config& | |
| 248 | + static_id(bool val) | |
| 249 | + { | |
| 250 | + static_id_ = val; | |
| 251 | + return *this; | |
| 252 | + } | |
| 253 | + | |
| 254 | + bool | |
| 255 | + pclm() const | |
| 256 | + { | |
| 257 | + return pclm_; | |
| 258 | + } | |
| 259 | + | |
| 260 | + Config& pclm(bool val); | |
| 261 | + | |
| 262 | + private: | |
| 263 | + void usage(std::string_view msg) const {}; | |
| 27 | 264 | |
| 28 | 265 | std::string forced_pdf_version_; |
| 29 | 266 | std::string extra_header_text_; |
| 30 | 267 | // For linearization only |
| 31 | 268 | std::string lin_pass1_filename_; |
| 32 | 269 | |
| 33 | - qpdf_object_stream_e object_stream_mode_{qpdf_o_preserve}; | |
| 270 | + qpdf_object_stream_e object_streams_{qpdf_o_preserve}; | |
| 271 | + qpdf_stream_decode_level_e stream_decode_level_{qpdf_dl_generalized}; | |
| 34 | 272 | |
| 35 | 273 | int forced_extension_level_{0}; |
| 36 | 274 | |
| ... | ... | @@ -38,18 +276,17 @@ namespace qpdf |
| 38 | 276 | bool normalize_content_{false}; |
| 39 | 277 | bool compress_streams_{true}; |
| 40 | 278 | bool compress_streams_set_{false}; |
| 41 | - qpdf_stream_decode_level_e stream_decode_level_{qpdf_dl_generalized}; | |
| 42 | 279 | bool stream_decode_level_set_{false}; |
| 43 | 280 | bool recompress_flate_{false}; |
| 44 | - bool qdf_mode_{false}; | |
| 45 | - bool preserve_unreferenced_objects_{false}; | |
| 281 | + bool qdf_{false}; | |
| 282 | + bool preserve_unreferenced_{false}; | |
| 46 | 283 | bool newline_before_endstream_{false}; |
| 47 | 284 | bool deterministic_id_{false}; |
| 48 | 285 | bool static_id_{false}; |
| 49 | 286 | bool suppress_original_object_ids_{false}; |
| 50 | 287 | bool direct_stream_lengths_{true}; |
| 51 | 288 | bool preserve_encryption_{true}; |
| 52 | - bool linearized_{false}; | |
| 289 | + bool linearize_{false}; | |
| 53 | 290 | bool pclm_{false}; |
| 54 | 291 | bool encrypt_use_aes_{false}; |
| 55 | 292 | }; // class Writer::Config | ... | ... |
qpdf/qpdf.testcov
| ... | ... | @@ -46,7 +46,6 @@ QPDFObjectHandle copy stream 1 |
| 46 | 46 | QPDF ignoring XRefStm in trailer 0 |
| 47 | 47 | SF_FlateLzwDecode PNG filter 0 |
| 48 | 48 | QPDF xref /Index is array 1 |
| 49 | -QPDFWriter encrypt object stream 0 | |
| 50 | 49 | QPDF exclude indirect length 0 |
| 51 | 50 | QPDF exclude encryption dictionary 0 |
| 52 | 51 | QPDF_Stream pipeStreamData with null pipeline 0 | ... | ... |