Commit bc6e62b947115c9fc0040461362bf3cbeec31d32
1 parent
f4598797
Refactor `QPDFWriter`: update `Writer` in `QPDFJob` usage to use `qpdf::Writer` …
…with encapsulated `Config`, replace `qcf` with `d_cfg` for improved consistency, and adjust related logic for maintainability.
Showing
7 changed files
with
71 additions
and
25 deletions
include/qpdf/QPDFJob.hh
| @@ -490,7 +490,7 @@ class QPDFJob | @@ -490,7 +490,7 @@ class QPDFJob | ||
| 490 | 490 | ||
| 491 | // Output generation | 491 | // Output generation |
| 492 | void doSplitPages(QPDF& pdf); | 492 | void doSplitPages(QPDF& pdf); |
| 493 | - void setWriterOptions(QPDFWriter&); | 493 | + void setWriterOptions(qpdf::Writer&); |
| 494 | void setEncryptionOptions(QPDFWriter&); | 494 | void setEncryptionOptions(QPDFWriter&); |
| 495 | void maybeFixWritePassword(int R, std::string& password); | 495 | void maybeFixWritePassword(int R, std::string& password); |
| 496 | void writeOutfile(QPDF& pdf); | 496 | void writeOutfile(QPDF& pdf); |
include/qpdf/QPDFWriter.hh
| @@ -43,6 +43,11 @@ | @@ -43,6 +43,11 @@ | ||
| 43 | #include <string_view> | 43 | #include <string_view> |
| 44 | #include <vector> | 44 | #include <vector> |
| 45 | 45 | ||
| 46 | +namespace qpdf | ||
| 47 | +{ | ||
| 48 | + class Writer; | ||
| 49 | +} | ||
| 50 | + | ||
| 46 | class QPDF; | 51 | class QPDF; |
| 47 | 52 | ||
| 48 | // This class implements a simple writer for saving QPDF objects to new PDF files. See comments | 53 | // This class implements a simple writer for saving QPDF objects to new PDF files. See comments |
| @@ -440,6 +445,8 @@ class QPDFWriter | @@ -440,6 +445,8 @@ class QPDFWriter | ||
| 440 | class NewObjTable; | 445 | class NewObjTable; |
| 441 | 446 | ||
| 442 | private: | 447 | private: |
| 448 | + friend class qpdf::Writer; | ||
| 449 | + | ||
| 443 | class Members; | 450 | class Members; |
| 444 | 451 | ||
| 445 | std::shared_ptr<Members> m; | 452 | std::shared_ptr<Members> m; |
libqpdf/QPDFJob.cc
| @@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
| 20 | #include <qpdf/QPDFPageObjectHelper.hh> | 20 | #include <qpdf/QPDFPageObjectHelper.hh> |
| 21 | #include <qpdf/QPDFSystemError.hh> | 21 | #include <qpdf/QPDFSystemError.hh> |
| 22 | #include <qpdf/QPDFUsage.hh> | 22 | #include <qpdf/QPDFUsage.hh> |
| 23 | -#include <qpdf/QPDFWriter.hh> | 23 | +#include <qpdf/QPDFWriter_private.hh> |
| 24 | #include <qpdf/QPDF_private.hh> | 24 | #include <qpdf/QPDF_private.hh> |
| 25 | #include <qpdf/QTC.hh> | 25 | #include <qpdf/QTC.hh> |
| 26 | #include <qpdf/QUtil.hh> | 26 | #include <qpdf/QUtil.hh> |
| @@ -476,7 +476,7 @@ QPDFJob::writeQPDF(QPDF& pdf) | @@ -476,7 +476,7 @@ QPDFJob::writeQPDF(QPDF& pdf) | ||
| 476 | if (!pdf.getWarnings().empty()) { | 476 | if (!pdf.getWarnings().empty()) { |
| 477 | m->warnings = true; | 477 | m->warnings = true; |
| 478 | } | 478 | } |
| 479 | - if (m->warnings && !m->qcf.suppress_warnings()) { | 479 | + if (m->warnings && !m->d_cfg.suppress_warnings()) { |
| 480 | if (createsOutput()) { | 480 | if (createsOutput()) { |
| 481 | *m->log->getWarn() | 481 | *m->log->getWarn() |
| 482 | << m->message_prefix | 482 | << m->message_prefix |
| @@ -744,7 +744,8 @@ QPDFJob::doCheck(QPDF& pdf) | @@ -744,7 +744,8 @@ QPDFJob::doCheck(QPDF& pdf) | ||
| 744 | 744 | ||
| 745 | // Write the file to nowhere, uncompressing streams. This causes full file traversal and | 745 | // Write the file to nowhere, uncompressing streams. This causes full file traversal and |
| 746 | // decoding of all streams we can decode. | 746 | // decoding of all streams we can decode. |
| 747 | - QPDFWriter w(pdf); | 747 | + Writer::Config cfg; |
| 748 | + Writer w(pdf, cfg); | ||
| 748 | Pl_Discard discard; | 749 | Pl_Discard discard; |
| 749 | w.setOutputPipeline(&discard); | 750 | w.setOutputPipeline(&discard); |
| 750 | w.setDecodeLevel(qpdf_dl_all); | 751 | w.setDecodeLevel(qpdf_dl_all); |
| @@ -1708,7 +1709,7 @@ QPDFJob::doProcessOnce( | @@ -1708,7 +1709,7 @@ QPDFJob::doProcessOnce( | ||
| 1708 | bool main_input) | 1709 | bool main_input) |
| 1709 | { | 1710 | { |
| 1710 | pdf = std::make_unique<QPDF>(); | 1711 | pdf = std::make_unique<QPDF>(); |
| 1711 | - pdf->doc().config(m->qcf.log(m->log)); | 1712 | + pdf->doc().config(m->d_cfg.log(m->log)); |
| 1712 | if (empty) { | 1713 | if (empty) { |
| 1713 | pdf->emptyPDF(); | 1714 | pdf->emptyPDF(); |
| 1714 | } else if (main_input && m->json_input) { | 1715 | } else if (main_input && m->json_input) { |
| @@ -1738,7 +1739,7 @@ QPDFJob::doProcess( | @@ -1738,7 +1739,7 @@ QPDFJob::doProcess( | ||
| 1738 | // was incorrectly encoded, there's a good chance we'd succeed here. | 1739 | // was incorrectly encoded, there's a good chance we'd succeed here. |
| 1739 | 1740 | ||
| 1740 | std::string ptemp; | 1741 | std::string ptemp; |
| 1741 | - if (password && !m->qcf.password_is_hex_key()) { | 1742 | + if (password && !m->d_cfg.password_is_hex_key()) { |
| 1742 | if (m->password_mode == QPDFJob::pm_hex_bytes) { | 1743 | if (m->password_mode == QPDFJob::pm_hex_bytes) { |
| 1743 | // Special case: handle --password-mode=hex-bytes for input password as well as output | 1744 | // Special case: handle --password-mode=hex-bytes for input password as well as output |
| 1744 | // password | 1745 | // password |
| @@ -1746,7 +1747,7 @@ QPDFJob::doProcess( | @@ -1746,7 +1747,7 @@ QPDFJob::doProcess( | ||
| 1746 | password = ptemp.c_str(); | 1747 | password = ptemp.c_str(); |
| 1747 | } | 1748 | } |
| 1748 | } | 1749 | } |
| 1749 | - if (!password || empty || m->qcf.password_is_hex_key() || m->suppress_password_recovery) { | 1750 | + if (!password || empty || m->d_cfg.password_is_hex_key() || m->suppress_password_recovery) { |
| 1750 | // There is no password, or we're not doing recovery, so just do the normal processing with | 1751 | // There is no password, or we're not doing recovery, so just do the normal processing with |
| 1751 | // the supplied password. | 1752 | // the supplied password. |
| 1752 | doProcessOnce(pdf, fn, password, empty, used_for_input, main_input); | 1753 | doProcessOnce(pdf, fn, password, empty, used_for_input, main_input); |
| @@ -2878,7 +2879,7 @@ parse_version(std::string const& full_version_string, std::string& version, int& | @@ -2878,7 +2879,7 @@ parse_version(std::string const& full_version_string, std::string& version, int& | ||
| 2878 | } | 2879 | } |
| 2879 | 2880 | ||
| 2880 | void | 2881 | void |
| 2881 | -QPDFJob::setWriterOptions(QPDFWriter& w) | 2882 | +QPDFJob::setWriterOptions(Writer& w) |
| 2882 | { | 2883 | { |
| 2883 | if (m->compression_level >= 0) { | 2884 | if (m->compression_level >= 0) { |
| 2884 | Pl_Flate::setCompressionLevel(m->compression_level); | 2885 | Pl_Flate::setCompressionLevel(m->compression_level); |
| @@ -3011,7 +3012,7 @@ QPDFJob::doSplitPages(QPDF& pdf) | @@ -3011,7 +3012,7 @@ QPDFJob::doSplitPages(QPDF& pdf) | ||
| 3011 | last = num_pages; | 3012 | last = num_pages; |
| 3012 | } | 3013 | } |
| 3013 | QPDF outpdf; | 3014 | QPDF outpdf; |
| 3014 | - outpdf.doc().config(m->qcf); | 3015 | + outpdf.doc().config(m->d_cfg); |
| 3015 | outpdf.emptyPDF(); | 3016 | outpdf.emptyPDF(); |
| 3016 | QPDFAcroFormDocumentHelper* out_afdh = | 3017 | QPDFAcroFormDocumentHelper* out_afdh = |
| 3017 | afdh.hasAcroForm() ? &outpdf.doc().acroform() : nullptr; | 3018 | afdh.hasAcroForm() ? &outpdf.doc().acroform() : nullptr; |
| @@ -3049,7 +3050,8 @@ QPDFJob::doSplitPages(QPDF& pdf) | @@ -3049,7 +3050,8 @@ QPDFJob::doSplitPages(QPDF& pdf) | ||
| 3049 | if (QUtil::same_file(m->infile_nm(), outfile.data())) { | 3050 | if (QUtil::same_file(m->infile_nm(), outfile.data())) { |
| 3050 | throw std::runtime_error("split pages would overwrite input file with " + outfile); | 3051 | throw std::runtime_error("split pages would overwrite input file with " + outfile); |
| 3051 | } | 3052 | } |
| 3052 | - QPDFWriter w(outpdf, outfile.c_str()); | 3053 | + Writer w(outpdf, m->w_cfg); |
| 3054 | + w.setOutputFilename(outfile.data()); | ||
| 3053 | setWriterOptions(w); | 3055 | setWriterOptions(w); |
| 3054 | w.write(); | 3056 | w.write(); |
| 3055 | doIfVerbose([&](Pipeline& v, std::string const& prefix) { | 3057 | doIfVerbose([&](Pipeline& v, std::string const& prefix) { |
| @@ -3074,9 +3076,8 @@ QPDFJob::writeOutfile(QPDF& pdf) | @@ -3074,9 +3076,8 @@ QPDFJob::writeOutfile(QPDF& pdf) | ||
| 3074 | if (m->json_version) { | 3076 | if (m->json_version) { |
| 3075 | writeJSON(pdf); | 3077 | writeJSON(pdf); |
| 3076 | } else { | 3078 | } else { |
| 3077 | - // QPDFWriter must have block scope so the output file will be closed after write() | ||
| 3078 | - // finishes. | ||
| 3079 | - QPDFWriter w(pdf); | 3079 | + // Writer must have block scope so the output file will be closed after write() finishes. |
| 3080 | + Writer w(pdf, m->w_cfg); | ||
| 3080 | if (!m->outfilename.empty()) { | 3081 | if (!m->outfilename.empty()) { |
| 3081 | w.setOutputFilename(m->outfilename.data()); | 3082 | w.setOutputFilename(m->outfilename.data()); |
| 3082 | } else { | 3083 | } else { |
libqpdf/QPDFJob_config.cc
| @@ -68,7 +68,7 @@ QPDFJob::Config* | @@ -68,7 +68,7 @@ QPDFJob::Config* | ||
| 68 | QPDFJob::Config::check() | 68 | QPDFJob::Config::check() |
| 69 | { | 69 | { |
| 70 | o.m->check = true; | 70 | o.m->check = true; |
| 71 | - o.m->qcf.check_mode(true); | 71 | + o.m->d_cfg.check_mode(true); |
| 72 | o.m->require_outfile = false; | 72 | o.m->require_outfile = false; |
| 73 | return this; | 73 | return this; |
| 74 | } | 74 | } |
| @@ -234,7 +234,7 @@ QPDFJob::Config::generateAppearances() | @@ -234,7 +234,7 @@ QPDFJob::Config::generateAppearances() | ||
| 234 | QPDFJob::Config* | 234 | QPDFJob::Config* |
| 235 | QPDFJob::Config::ignoreXrefStreams() | 235 | QPDFJob::Config::ignoreXrefStreams() |
| 236 | { | 236 | { |
| 237 | - o.m->qcf.ignore_xref_streams(true); | 237 | + o.m->d_cfg.ignore_xref_streams(true); |
| 238 | return this; | 238 | return this; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| @@ -416,7 +416,7 @@ QPDFJob::Config::noOriginalObjectIds() | @@ -416,7 +416,7 @@ QPDFJob::Config::noOriginalObjectIds() | ||
| 416 | QPDFJob::Config* | 416 | QPDFJob::Config* |
| 417 | QPDFJob::Config::noWarn() | 417 | QPDFJob::Config::noWarn() |
| 418 | { | 418 | { |
| 419 | - o.m->qcf.suppress_warnings(true); | 419 | + o.m->d_cfg.suppress_warnings(true); |
| 420 | return this; | 420 | return this; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| @@ -466,7 +466,7 @@ QPDFJob::Config::password(std::string const& parameter) | @@ -466,7 +466,7 @@ QPDFJob::Config::password(std::string const& parameter) | ||
| 466 | QPDFJob::Config* | 466 | QPDFJob::Config* |
| 467 | QPDFJob::Config::passwordIsHexKey() | 467 | QPDFJob::Config::passwordIsHexKey() |
| 468 | { | 468 | { |
| 469 | - o.m->qcf.password_is_hex_key(true); | 469 | + o.m->d_cfg.password_is_hex_key(true); |
| 470 | return this; | 470 | return this; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| @@ -663,7 +663,7 @@ QPDFJob::Config::suppressPasswordRecovery() | @@ -663,7 +663,7 @@ QPDFJob::Config::suppressPasswordRecovery() | ||
| 663 | QPDFJob::Config* | 663 | QPDFJob::Config* |
| 664 | QPDFJob::Config::suppressRecovery() | 664 | QPDFJob::Config::suppressRecovery() |
| 665 | { | 665 | { |
| 666 | - o.m->qcf.surpress_recovery(true); | 666 | + o.m->d_cfg.surpress_recovery(true); |
| 667 | return this; | 667 | return this; |
| 668 | } | 668 | } |
| 669 | 669 |
libqpdf/QPDFWriter.cc
| @@ -292,9 +292,8 @@ namespace qpdf::impl | @@ -292,9 +292,8 @@ namespace qpdf::impl | ||
| 292 | Writer(QPDF& qpdf, QPDFWriter& w) : | 292 | Writer(QPDF& qpdf, QPDFWriter& w) : |
| 293 | Common(qpdf.doc()), | 293 | Common(qpdf.doc()), |
| 294 | lin(qpdf.doc().linearization()), | 294 | lin(qpdf.doc().linearization()), |
| 295 | - root_og( | ||
| 296 | - qpdf.getRoot().getObjGen().isIndirect() ? qpdf.getRoot().getObjGen() | ||
| 297 | - : QPDFObjGen(-1, 0)), | 295 | + cfg(true), |
| 296 | + root_og(qpdf.getRoot().indirect() ? qpdf.getRoot().id_gen() : QPDFObjGen(-1, 0)), | ||
| 298 | pipeline_stack(pipeline) | 297 | pipeline_stack(pipeline) |
| 299 | { | 298 | { |
| 300 | } | 299 | } |
| @@ -474,6 +473,7 @@ namespace qpdf::impl | @@ -474,6 +473,7 @@ namespace qpdf::impl | ||
| 474 | class QPDFWriter::Members: impl::Writer | 473 | class QPDFWriter::Members: impl::Writer |
| 475 | { | 474 | { |
| 476 | friend class QPDFWriter; | 475 | friend class QPDFWriter; |
| 476 | + friend class qpdf::Writer; | ||
| 477 | 477 | ||
| 478 | public: | 478 | public: |
| 479 | Members(QPDFWriter& w, QPDF& qpdf) : | 479 | Members(QPDFWriter& w, QPDF& qpdf) : |
| @@ -482,6 +482,11 @@ class QPDFWriter::Members: impl::Writer | @@ -482,6 +482,11 @@ class QPDFWriter::Members: impl::Writer | ||
| 482 | } | 482 | } |
| 483 | }; | 483 | }; |
| 484 | 484 | ||
| 485 | +qpdf::Writer::Writer(QPDF& qpdf, Config cfg) : | ||
| 486 | + QPDFWriter(qpdf) | ||
| 487 | +{ | ||
| 488 | + m->cfg = cfg; | ||
| 489 | +} | ||
| 485 | QPDFWriter::QPDFWriter(QPDF& pdf) : | 490 | QPDFWriter::QPDFWriter(QPDF& pdf) : |
| 486 | m(std::make_shared<Members>(*this, pdf)) | 491 | m(std::make_shared<Members>(*this, pdf)) |
| 487 | { | 492 | { |
libqpdf/qpdf/QPDFJob_private.hh
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | 5 | ||
| 6 | #include <qpdf/ClosedFileInputSource.hh> | 6 | #include <qpdf/ClosedFileInputSource.hh> |
| 7 | #include <qpdf/QPDFLogger.hh> | 7 | #include <qpdf/QPDFLogger.hh> |
| 8 | +#include <qpdf/QPDFWriter_private.hh> | ||
| 8 | #include <qpdf/QPDF_private.hh> | 9 | #include <qpdf/QPDF_private.hh> |
| 9 | 10 | ||
| 10 | // A selection of pages from a single input PDF to be included in the output. This corresponds to a | 11 | // A selection of pages from a single input PDF to be included in the output. This corresponds to a |
| @@ -150,7 +151,7 @@ class QPDFJob::Members | @@ -150,7 +151,7 @@ class QPDFJob::Members | ||
| 150 | 151 | ||
| 151 | public: | 152 | public: |
| 152 | Members(QPDFJob& job) : | 153 | Members(QPDFJob& job) : |
| 153 | - log(qcf.log()), | 154 | + log(d_cfg.log()), |
| 154 | inputs(job) | 155 | inputs(job) |
| 155 | { | 156 | { |
| 156 | } | 157 | } |
| @@ -168,7 +169,8 @@ class QPDFJob::Members | @@ -168,7 +169,8 @@ class QPDFJob::Members | ||
| 168 | static int constexpr DEFAULT_OI_MIN_AREA = 16384; | 169 | static int constexpr DEFAULT_OI_MIN_AREA = 16384; |
| 169 | static int constexpr DEFAULT_II_MIN_BYTES = 1024; | 170 | static int constexpr DEFAULT_II_MIN_BYTES = 1024; |
| 170 | 171 | ||
| 171 | - qpdf::Doc::Config qcf; | 172 | + qpdf::Doc::Config d_cfg; |
| 173 | + qpdf::Writer::Config w_cfg; | ||
| 172 | std::shared_ptr<QPDFLogger> log; | 174 | std::shared_ptr<QPDFLogger> log; |
| 173 | std::string message_prefix{"qpdf"}; | 175 | std::string message_prefix{"qpdf"}; |
| 174 | bool warnings{false}; | 176 | bool warnings{false}; |
libqpdf/qpdf/QPDFWriter_private.hh
| @@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
| 6 | #include <qpdf/ObjTable.hh> | 6 | #include <qpdf/ObjTable.hh> |
| 7 | #include <qpdf/Pipeline_private.hh> | 7 | #include <qpdf/Pipeline_private.hh> |
| 8 | #include <qpdf/QPDF.hh> | 8 | #include <qpdf/QPDF.hh> |
| 9 | +#include <qpdf/QPDFUsage.hh> | ||
| 9 | 10 | ||
| 10 | // This file is intended for inclusion by QPDFWriter, QPDF, QPDF_optimization and QPDF_linearization | 11 | // This file is intended for inclusion by QPDFWriter, QPDF, QPDF_optimization and QPDF_linearization |
| 11 | // only. | 12 | // only. |
| @@ -17,12 +18,24 @@ namespace qpdf | @@ -17,12 +18,24 @@ namespace qpdf | ||
| 17 | class Writer; | 18 | class Writer; |
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | - class Writer | 21 | + class Writer: public QPDFWriter |
| 21 | { | 22 | { |
| 22 | public: | 23 | public: |
| 23 | class Config | 24 | class Config |
| 24 | { | 25 | { |
| 25 | public: | 26 | public: |
| 27 | + Config() = default; | ||
| 28 | + Config(Config const&) = default; | ||
| 29 | + Config(Config&&) = delete; | ||
| 30 | + Config& operator=(Config const&) = default; | ||
| 31 | + Config& operator=(Config&&) = delete; | ||
| 32 | + ~Config() = default; | ||
| 33 | + | ||
| 34 | + Config(bool permissive) : | ||
| 35 | + permissive_(permissive) | ||
| 36 | + { | ||
| 37 | + } | ||
| 38 | + | ||
| 26 | bool | 39 | bool |
| 27 | linearize() const | 40 | linearize() const |
| 28 | { | 41 | { |
| @@ -258,7 +271,13 @@ namespace qpdf | @@ -258,7 +271,13 @@ namespace qpdf | ||
| 258 | Config& pclm(bool val); | 271 | Config& pclm(bool val); |
| 259 | 272 | ||
| 260 | private: | 273 | private: |
| 261 | - void usage(std::string_view msg) const {}; | 274 | + void |
| 275 | + usage(std::string const& msg) const | ||
| 276 | + { | ||
| 277 | + if (!permissive_) { | ||
| 278 | + throw QPDFUsage(msg); | ||
| 279 | + } | ||
| 280 | + } | ||
| 262 | 281 | ||
| 263 | std::string forced_pdf_version_; | 282 | std::string forced_pdf_version_; |
| 264 | std::string extra_header_text_; | 283 | std::string extra_header_text_; |
| @@ -287,7 +306,19 @@ namespace qpdf | @@ -287,7 +306,19 @@ namespace qpdf | ||
| 287 | bool linearize_{false}; | 306 | bool linearize_{false}; |
| 288 | bool pclm_{false}; | 307 | bool pclm_{false}; |
| 289 | bool encrypt_use_aes_{false}; | 308 | bool encrypt_use_aes_{false}; |
| 309 | + | ||
| 310 | + bool permissive_{true}; | ||
| 290 | }; // class Writer::Config | 311 | }; // class Writer::Config |
| 312 | + | ||
| 313 | + Writer() = delete; | ||
| 314 | + Writer(Writer const&) = delete; | ||
| 315 | + Writer(Writer&&) = delete; | ||
| 316 | + Writer& operator=(Writer const&) = delete; | ||
| 317 | + Writer& operator=(Writer&&) = delete; | ||
| 318 | + ~Writer() = default; | ||
| 319 | + | ||
| 320 | + Writer(QPDF& qpdf, Config cfg); | ||
| 321 | + | ||
| 291 | }; // class Writer | 322 | }; // class Writer |
| 292 | } // namespace qpdf | 323 | } // namespace qpdf |
| 293 | 324 |