From b520c1504a3e217608405b196be897fe3a5b104e Mon Sep 17 00:00:00 2001 From: m-holger Date: Wed, 15 Oct 2025 20:37:00 +0100 Subject: [PATCH] Refactor `Config` interface: add accessor and mutator methods for configuration fields, replace direct member access across the codebase, and streamline related logic. --- libqpdf/QPDF.cc | 26 +++++++++++++------------- libqpdf/QPDFJob.cc | 14 +------------- libqpdf/QPDF_Stream.cc | 9 +-------- libqpdf/QPDF_encryption.cc | 2 +- libqpdf/QPDF_linearization.cc | 16 ++++++++-------- libqpdf/QPDF_objects.cc | 18 +++++++++--------- libqpdf/qpdf/QPDF_private.hh | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 7 files changed, 148 insertions(+), 56 deletions(-) diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index dc87647..cab82c7 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -231,7 +231,7 @@ QPDF::closeInputSource() void QPDF::setPasswordIsHexKey(bool val) { - m->cf.provided_password_is_hex_key_ = val; + m->cf.provided_password_is_hex_key(val); } void @@ -250,50 +250,50 @@ QPDF::registerStreamFilter( void QPDF::setIgnoreXRefStreams(bool val) { - m->cf.ignore_xref_streams_ = val; + m->cf.ignore_xref_streams(val); } std::shared_ptr QPDF::getLogger() { - return m->cf.log_; + return m->cf.log(); } void QPDF::setLogger(std::shared_ptr l) { - m->cf.log_ = l; + m->cf.log(l); } void QPDF::setOutputStreams(std::ostream* out, std::ostream* err) { setLogger(QPDFLogger::create()); - m->cf.log_->setOutputStreams(out, err); + m->cf.log()->setOutputStreams(out, err); } void QPDF::setSuppressWarnings(bool val) { - m->cf.suppress_warnings_ = val; + m->cf.suppress_warnings(val); } void QPDF::setMaxWarnings(size_t val) { - m->cf.max_warnings_ = val; + m->cf.max_warnings(val); } void QPDF::setAttemptRecovery(bool val) { - m->cf.attempt_recovery_ = val; + (void)m->cf.attempt_recovery(val); } void QPDF::setImmediateCopyFrom(bool val) { - m->cf.immediate_copy_from_ = val; + (void)m->cf.immediate_copy_from(val); } std::vector @@ -371,12 +371,12 @@ QPDF::warn(QPDFExc const& e) void Common::warn(QPDFExc const& e) { - if (m->cf.max_warnings_ > 0 && m->warnings.size() >= m->cf.max_warnings_) { + if (cf.max_warnings() > 0 && m->warnings.size() >= cf.max_warnings()) { stopOnError("Too many warnings - file is too badly damaged"); } m->warnings.emplace_back(e); - if (!m->cf.suppress_warnings_) { - *m->cf.log_->getWarn() << "WARNING: " << m->warnings.back().what() << "\n"; + if (!cf.suppress_warnings()) { + *cf.log()->getWarn() << "WARNING: " << m->warnings.back().what() << "\n"; } } @@ -714,7 +714,7 @@ QPDF::getRoot() } else if ( // Check_mode is an interim solution to request #810 pending a more comprehensive review of // the approach to more extensive checks and warning levels. - m->cf.check_mode_ && !root.getKey("/Type").isNameAndEquals("/Catalog")) { + m->cf.check_mode() && !root.getKey("/Type").isNameAndEquals("/Catalog")) { warn(m->c.damagedPDF("", -1, "catalog /Type entry missing or invalid")); root.replaceKey("/Type", "/Catalog"_qpdf); } diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 8ce7965..4543fc9 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -33,18 +33,6 @@ using namespace qpdf; using QDoc = QPDF::Doc; using Pages = QDoc::Pages; -// JobSetter class is restricted to QPDFJob. -class QDoc::JobSetter -{ - public: - // Enable enhanced warnings for pdf file checking. - static void - setCheckMode(QPDF& qpdf, bool val) - { - qpdf.m->cf.check_mode_ = val; - } -}; - namespace { class ImageOptimizer final: public QPDFObjectHandle::StreamDataProvider @@ -749,7 +737,7 @@ QPDFJob::doCheck(QPDF& pdf) bool okay = true; auto& cout = *m->log->getInfo(); cout << "checking " << m->infile_name() << "\n"; - QDoc::JobSetter::setCheckMode(pdf, true); + pdf.doc().config().check_mode(true); try { int extension_level = pdf.getExtensionLevel(); cout << "PDF Version: " << pdf.getPDFVersion(); diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index b54acc4..0bd46c0 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -27,12 +27,6 @@ using namespace qpdf; using Streams = QPDF::Doc::Objects::Streams; -bool -Streams::immediate_copy_from() const -{ - return qpdf.m->cf.immediate_copy_from_; -} - class Streams::Copier final: public QPDFObjectHandle::StreamDataProvider { class Data @@ -308,14 +302,13 @@ Stream::copy_data_to(Stream& dest) { qpdf_expect(dest); auto s = stream(); - auto& streams = qpdf()->doc().objects().streams(); auto& d_streams = dest.qpdf()->doc().objects().streams(); auto dict = dest.getDict(); // Copy information from the foreign stream so we can pipe its data later without keeping the // original QPDF object around. - if (streams.immediate_copy_from() && !s->stream_data) { + if (qpdf()->doc().config().immediate_copy_from() && !s->stream_data) { // Pull the stream data into a buffer before attempting the copy operation. Do it on the // source stream so that if the source stream is copied multiple times, we don't have to // keep duplicating the memory. diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index abcb5b7..6998698 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -904,7 +904,7 @@ QPDF::EncryptionParameters::initialize(QPDF& qpdf) } Encryption data(V, R, Length / 8, p, O, U, OE, UE, Perms, id1, encrypt_metadata); - if (qm.cf.provided_password_is_hex_key_) { + if (qm.cf.provided_password_is_hex_key()) { // ignore passwords in file encryption_key = QUtil::hex_decode(provided_password); return; diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index a405205..950d65e 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -1095,7 +1095,7 @@ QPDF::showLinearizationData() void Lin::dumpLinearizationDataInternal() { - auto& info = *m->cf.log_->getInfo(); + auto& info = *cf.log()->getInfo(); info << m->file->getName() << ": linearization data:\n\n"; @@ -1134,7 +1134,7 @@ Lin::adjusted_offset(qpdf_offset_t offset) void Lin::dumpHPageOffset() { - auto& info = *m->cf.log_->getInfo(); + auto& info = *cf.log()->getInfo(); HPageOffset& t = m->page_offset_hints; info << "min_nobjects: " << t.min_nobjects << "\n" << "first_page_offset: " << adjusted_offset(t.first_page_offset) << "\n" @@ -1170,7 +1170,7 @@ Lin::dumpHPageOffset() void Lin::dumpHSharedObject() { - auto& info = *m->cf.log_->getInfo(); + auto& info = *cf.log()->getInfo(); HSharedObject& t = m->shared_object_hints; info << "first_shared_obj: " << t.first_shared_obj << "\n" << "first_shared_offset: " << adjusted_offset(t.first_shared_offset) << "\n" @@ -1198,11 +1198,11 @@ Lin::dumpHSharedObject() void Lin::dumpHGeneric(HGeneric& t) { - *m->cf.log_->getInfo() << "first_object: " << t.first_object << "\n" - << "first_object_offset: " << adjusted_offset(t.first_object_offset) - << "\n" - << "nobjects: " << t.nobjects << "\n" - << "group_length: " << t.group_length << "\n"; + *cf.log()->getInfo() << "first_object: " << t.first_object << "\n" + << "first_object_offset: " << adjusted_offset(t.first_object_offset) + << "\n" + << "nobjects: " << t.nobjects << "\n" + << "group_length: " << t.group_length << "\n"; } template diff --git a/libqpdf/QPDF_objects.cc b/libqpdf/QPDF_objects.cc index 4e9ed6b..5960e9c 100644 --- a/libqpdf/QPDF_objects.cc +++ b/libqpdf/QPDF_objects.cc @@ -157,7 +157,7 @@ Objects::parse(char const* password) throw damagedPDF("", -1, std::string("error reading xref: ") + e.what()); } } catch (QPDFExc& e) { - if (m->cf.attempt_recovery_) { + if (cf.attempt_recovery()) { reconstruct_xref(e, xref_offset > 0); } else { throw; @@ -736,7 +736,7 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) } if (cur_trailer.hasKey("/XRefStm")) { - if (m->cf.ignore_xref_streams_) { + if (cf.ignore_xref_streams()) { QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer"); } else { if (cur_trailer.getKey("/XRefStm").isInteger()) { @@ -763,7 +763,7 @@ Objects::read_xrefTable(qpdf_offset_t xref_offset) qpdf_offset_t Objects::read_xrefStream(qpdf_offset_t xref_offset, bool in_stream_recovery) { - if (!m->cf.ignore_xref_streams_) { + if (!cf.ignore_xref_streams()) { QPDFObjectHandle xref_obj; try { m->in_read_xref_stream = true; @@ -1073,7 +1073,7 @@ Objects::insertFreeXrefEntry(QPDFObjGen og) void QPDF::showXRefTable() { - auto& cout = *m->cf.log_->getInfo(); + auto& cout = *m->cf.log()->getInfo(); for (auto const& iter: m->xref_table) { QPDFObjGen const& og = iter.first; QPDFXRefEntry const& entry = iter.second; @@ -1084,15 +1084,15 @@ QPDF::showXRefTable() break; case 2: - *m->cf.log_->getInfo() << "compressed; stream = " << entry.getObjStreamNumber() - << ", index = " << entry.getObjStreamIndex(); + *m->cf.log()->getInfo() << "compressed; stream = " << entry.getObjStreamNumber() + << ", index = " << entry.getObjStreamIndex(); break; default: throw std::logic_error("unknown cross-reference table type while showing xref_table"); break; } - m->cf.log_->info("\n"); + m->cf.log()->info("\n"); } } @@ -1248,7 +1248,7 @@ Objects::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offse throw damagedPDF("expected endstream"); } } catch (QPDFExc& e) { - if (m->cf.attempt_recovery_) { + if (cf.attempt_recovery()) { warn(e); length = recoverStreamLength(m->file, og, stream_offset); } else { @@ -1431,7 +1431,7 @@ Objects::readObjectAtOffset( QPDFObjGen og; setLastObjectDescription(description, exp_og); - if (!m->cf.attempt_recovery_) { + if (!cf.attempt_recovery()) { try_recovery = false; } diff --git a/libqpdf/qpdf/QPDF_private.hh b/libqpdf/qpdf/QPDF_private.hh index 4794e98..9e91505 100644 --- a/libqpdf/qpdf/QPDF_private.hh +++ b/libqpdf/qpdf/QPDF_private.hh @@ -27,13 +27,117 @@ namespace qpdf public: class Config { - friend class QPDF; - + public: Config() : log_(QPDFLogger::defaultLogger()) { } + bool + provided_password_is_hex_key() const + { + return provided_password_is_hex_key_; + } + + Config& + provided_password_is_hex_key(bool val) + { + provided_password_is_hex_key_ = val; + return *this; + } + + bool + ignore_xref_streams() const + { + return ignore_xref_streams_; + } + + Config& + ignore_xref_streams(bool val) + { + ignore_xref_streams_ = val; + return *this; + } + + std::shared_ptr + log() const + { + return log_; + } + + Config& + log(std::shared_ptr val) + { + log_ = val; + return *this; + } + + bool + suppress_warnings() const + { + return suppress_warnings_; + } + + Config& + suppress_warnings(bool val) + { + suppress_warnings_ = val; + return *this; + } + + size_t + max_warnings() const + { + return max_warnings_; + } + + Config& + max_warnings(size_t val) + { + max_warnings_ = val; + return *this; + } + + bool + attempt_recovery() const + { + return attempt_recovery_; + } + + Config& + attempt_recovery(bool val) + { + attempt_recovery_ = val; + return *this; + } + + bool + immediate_copy_from() const + { + return immediate_copy_from_; + } + + Config& + immediate_copy_from(bool val) + { + immediate_copy_from_ = val; + return *this; + } + + bool + check_mode() const + { + return check_mode_; + } + + Config& + check_mode(bool val) + { + check_mode_ = val; + return *this; + } + + private: std::shared_ptr log_; size_t max_warnings_{0}; @@ -322,7 +426,6 @@ class QPDF::Doc { public: class Encryption; - class JobSetter; class Linearization; class Objects; class Pages; @@ -378,6 +481,7 @@ class QPDF::Doc QPDF& qpdf; QPDF::Members* m; + qpdf::Doc::Config& cf; QPDF::Doc::Pages& pages; }; @@ -394,6 +498,12 @@ class QPDF::Doc { } + qpdf::Doc::Config& + config() + { + return cf; + } + inline Linearization& linearization(); inline Objects& objects(); @@ -772,7 +882,7 @@ class QPDF::Doc::Objects: Common return copier_; } - bool immediate_copy_from() const; + // bool immediate_copy_from() const; private: std::shared_ptr copier_; @@ -1072,6 +1182,7 @@ class QPDF::Doc::Resolver inline QPDF::Doc::Common::Common(QPDF& qpdf, QPDF::Members* m) : qpdf(qpdf), m(m), + cf(m->cf), pages(m->pages) { } -- libgit2 0.21.4