diff options
author | Jay Berkenbilt <jberkenbilt@users.noreply.github.com> | 2022-07-24 20:41:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-24 20:41:33 +0200 |
commit | 5696a507b6dacf34d066810a3f2fca3525eb02f5 (patch) | |
tree | b0009760e0f76c28aa99581e4bc6087adf93749f /libqpdf/QPDF.cc | |
parent | 6f1041afb8e6d1f57169cd4c79f42a7c1ce94da8 (diff) | |
parent | 8b4afa428e9caa1a34cad434dfe8a3e01e5a24d3 (diff) | |
download | qpdf-5696a507b6dacf34d066810a3f2fca3525eb02f5.tar.zst |
Merge pull request #731 from m-holger/og_unparse
Tidy QPDFObjGen related code
Diffstat (limited to 'libqpdf/QPDF.cc')
-rw-r--r-- | libqpdf/QPDF.cc | 226 |
1 files changed, 80 insertions, 146 deletions
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 86a4e3d2..a0f0f9e1 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -113,15 +113,13 @@ namespace QPDF::ForeignStreamData::ForeignStreamData( std::shared_ptr<EncryptionParameters> encp, std::shared_ptr<InputSource> file, - int foreign_objid, - int foreign_generation, + QPDFObjGen const& foreign_og, qpdf_offset_t offset, size_t length, QPDFObjectHandle local_dict) : encp(encp), file(file), - foreign_objid(foreign_objid), - foreign_generation(foreign_generation), + foreign_og(foreign_og), offset(offset), length(length), local_dict(local_dict) @@ -137,22 +135,19 @@ QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider( bool QPDF::CopiedStreamDataProvider::provideStreamData( - int objid, - int generation, + QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) { - std::shared_ptr<ForeignStreamData> foreign_data = - this->foreign_stream_data[QPDFObjGen(objid, generation)]; + std::shared_ptr<ForeignStreamData> foreign_data = foreign_stream_data[og]; bool result = false; if (foreign_data.get()) { result = destination_qpdf.pipeForeignStreamData( foreign_data, pipeline, suppress_warnings, will_retry); QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1); } else { - QPDFObjectHandle foreign_stream = - this->foreign_streams[QPDFObjGen(objid, generation)]; + auto foreign_stream = foreign_streams[og]; result = foreign_stream.pipeStreamData( pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry); QTC::TC( @@ -176,17 +171,16 @@ QPDF::CopiedStreamDataProvider::registerForeignStream( this->foreign_stream_data[local_og] = foreign_stream; } -QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, int objid, int gen) : +QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen const& og) : qpdf(qpdf), - objid(objid), - gen(gen) + og(og) { } void QPDF::StringDecrypter::decryptString(std::string& val) { - qpdf->decryptString(val, objid, gen); + qpdf->decryptString(val, og); } std::string const& @@ -205,8 +199,6 @@ QPDF::EncryptionParameters::EncryptionParameters() : cf_stream(e_none), cf_string(e_none), cf_file(e_none), - cached_key_objid(0), - cached_key_generation(0), user_password_matched(false), owner_password_matched(false) { @@ -631,7 +623,7 @@ QPDF::reconstruct_xref(QPDFExc& e) (!this->m->trailer.isInitialized()) && (t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) { QPDFObjectHandle t = - readObject(this->m->file, "trailer", 0, 0, false); + readObject(this->m->file, "trailer", QPDFObjGen(), false); if (!t.isDictionary()) { // Oh well. It was worth a try. } else { @@ -969,7 +961,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) // Set offset to previous xref table if any QPDFObjectHandle cur_trailer = - readObject(this->m->file, "trailer", 0, 0, false); + readObject(this->m->file, "trailer", QPDFObjGen(), false); if (!cur_trailer.isDictionary()) { QTC::TC("qpdf", "QPDF missing trailer"); throw QPDFExc( @@ -1055,12 +1047,11 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset) { bool found = false; if (!this->m->ignore_xref_streams) { - int xobj; - int xgen; + QPDFObjGen x_og; QPDFObjectHandle xref_obj; try { xref_obj = readObjectAtOffset( - false, xref_offset, "xref stream", 0, 0, xobj, xgen); + false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og); } catch (QPDFExc&) { // ignore -- report error below } @@ -1363,7 +1354,7 @@ QPDF::showXRefTable() for (auto const& iter: this->m->xref_table) { QPDFObjGen const& og = iter.first; QPDFXRefEntry const& entry = iter.second; - cout << og.getObj() << "/" << og.getGen() << ": "; + cout << og.unparse('/') << ": "; switch (entry.getType()) { case 1: cout << "uncompressed; offset = " << entry.getOffset(); @@ -1405,9 +1396,8 @@ QPDF::fixDanglingReferences(bool force) // For each non-scalar item to process, put it in the queue. std::list<QPDFObjectHandle> queue; queue.push_back(this->m->trailer); - for (auto const& iter: to_process) { - QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect( - this, iter.getObj(), iter.getGen()); + for (auto const& og: to_process) { + QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og); if (obj.isDictionary() || obj.isArray()) { queue.push_back(obj); } else if (obj.isStream()) { @@ -1473,29 +1463,24 @@ QPDF::getAllObjects() std::vector<QPDFObjectHandle> result; for (auto const& iter: this->m->obj_cache) { QPDFObjGen const& og = iter.first; - result.push_back( - // line-break - QPDFObjectHandle::Factory::newIndirect( - this, og.getObj(), og.getGen())); + result.push_back(QPDFObjectHandle::Factory::newIndirect(this, og)); } return result; } void QPDF::setLastObjectDescription( - std::string const& description, int objid, int generation) + std::string const& description, QPDFObjGen const& og) { this->m->last_object_description.clear(); if (!description.empty()) { this->m->last_object_description += description; - if (objid > 0) { + if (og.isIndirect()) { this->m->last_object_description += ": "; } } - if (objid > 0) { - this->m->last_object_description += "object " + - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation); + if (og.isIndirect()) { + this->m->last_object_description += "object " + og.unparse(' '); } } @@ -1503,19 +1488,17 @@ QPDFObjectHandle QPDF::readObject( std::shared_ptr<InputSource> input, std::string const& description, - int objid, - int generation, + QPDFObjGen const& og, bool in_object_stream) { - setLastObjectDescription(description, objid, generation); + setLastObjectDescription(description, og); qpdf_offset_t offset = input->tell(); bool empty = false; std::shared_ptr<StringDecrypter> decrypter_ph; StringDecrypter* decrypter = 0; if (this->m->encp->encrypted && (!in_object_stream)) { - decrypter_ph = - std::make_shared<StringDecrypter>(this, objid, generation); + decrypter_ph = std::make_shared<StringDecrypter>(this, og); decrypter = decrypter_ph.get(); } QPDFObjectHandle object = QPDFObjectHandle::parse( @@ -1657,14 +1640,13 @@ QPDF::readObject( } catch (QPDFExc& e) { if (this->m->attempt_recovery) { warn(e); - length = recoverStreamLength( - input, objid, generation, stream_offset); + length = recoverStreamLength(input, og, stream_offset); } else { throw e; } } object = QPDFObjectHandle::Factory::newStream( - this, objid, generation, object, stream_offset, length); + this, og, object, stream_offset, length); } else { input->seek(cur_offset, SEEK_SET); } @@ -1692,8 +1674,7 @@ QPDF::findEndstream() size_t QPDF::recoverStreamLength( std::shared_ptr<InputSource> input, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t stream_offset) { // Try to reconstruct stream length by looking for @@ -1718,11 +1699,10 @@ QPDF::recoverStreamLength( if (length) { qpdf_offset_t this_obj_offset = 0; - QPDFObjGen this_obj(0, 0); + QPDFObjGen this_og; // Make sure this is inside this object for (auto const& iter: this->m->xref_table) { - QPDFObjGen const& og = iter.first; QPDFXRefEntry const& entry = iter.second; if (entry.getType() == 1) { qpdf_offset_t obj_offset = entry.getOffset(); @@ -1730,12 +1710,11 @@ QPDF::recoverStreamLength( ((this_obj_offset == 0) || (this_obj_offset > obj_offset))) { this_obj_offset = obj_offset; - this_obj = og; + this_og = iter.first; } } } - if (this_obj_offset && (this_obj.getObj() == objid) && - (this_obj.getGen() == generation)) { + if (this_obj_offset && (this_og == og)) { // Well, we found endstream\nendobj within the space // allowed for this object, so we're probably in good // shape. @@ -1777,13 +1756,11 @@ QPDF::readObjectAtOffset( bool try_recovery, qpdf_offset_t offset, std::string const& description, - int exp_objid, - int exp_generation, - int& objid, - int& generation) + QPDFObjGen const& exp_og, + QPDFObjGen& og) { bool check_og = true; - if (exp_objid == 0) { + if (exp_og.getObj() == 0) { // This method uses an expect object ID of 0 to indicate that // we don't know or don't care what the actual object ID is at // this offset. This is true when we read the xref stream and @@ -1795,7 +1772,7 @@ QPDF::readObjectAtOffset( check_og = false; try_recovery = false; } else { - setLastObjectDescription(description, exp_objid, exp_generation); + setLastObjectDescription(description, exp_og); } if (!this->m->attempt_recovery) { @@ -1841,9 +1818,9 @@ QPDF::readObjectAtOffset( offset, "expected n n obj"); } - objid = QUtil::string_to_int(tobjid.getValue().c_str()); - generation = QUtil::string_to_int(tgen.getValue().c_str()); - + int objid = QUtil::string_to_int(tobjid.getValue().c_str()); + int generation = QUtil::string_to_int(tgen.getValue().c_str()); + og = QPDFObjGen(objid, generation); if (objid == 0) { QTC::TC("qpdf", "QPDF object id 0"); throw QPDFExc( @@ -1853,17 +1830,14 @@ QPDF::readObjectAtOffset( offset, "object with ID 0"); } - - if (check_og && - (!((objid == exp_objid) && (generation == exp_generation)))) { + if (check_og && (exp_og != og)) { QTC::TC("qpdf", "QPDF err wrong objid/generation"); QPDFExc e( qpdf_e_damaged_pdf, this->m->file->getName(), this->m->last_object_description, offset, - (std::string("expected ") + QUtil::int_to_string(exp_objid) + - " " + QUtil::int_to_string(exp_generation) + " obj")); + (std::string("expected ") + exp_og.unparse(' ') + " obj")); if (try_recovery) { // Will be retried below throw e; @@ -1877,18 +1851,12 @@ QPDF::readObjectAtOffset( if (try_recovery) { // Try again after reconstructing xref table reconstruct_xref(e); - QPDFObjGen og(exp_objid, exp_generation); - if (this->m->xref_table.count(og) && - (this->m->xref_table[og].getType() == 1)) { - qpdf_offset_t new_offset = this->m->xref_table[og].getOffset(); + if (this->m->xref_table.count(exp_og) && + (this->m->xref_table[exp_og].getType() == 1)) { + qpdf_offset_t new_offset = + this->m->xref_table[exp_og].getOffset(); QPDFObjectHandle result = readObjectAtOffset( - false, - new_offset, - description, - exp_objid, - exp_generation, - objid, - generation); + false, new_offset, description, exp_og, og); QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset"); return result; } else { @@ -1898,8 +1866,7 @@ QPDF::readObjectAtOffset( "", 0, std::string( - "object " + QUtil::int_to_string(exp_objid) + " " + - QUtil::int_to_string(exp_generation) + + "object " + exp_og.unparse(' ') + " not found in file after regenerating" " cross reference table")); return QPDFObjectHandle::newNull(); @@ -1909,8 +1876,7 @@ QPDF::readObjectAtOffset( } } - QPDFObjectHandle oh = - readObject(this->m->file, description, objid, generation, false); + QPDFObjectHandle oh = readObject(this->m->file, description, og, false); if (!(readToken(this->m->file) == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { @@ -1922,7 +1888,6 @@ QPDF::readObjectAtOffset( "expected endobj"); } - QPDFObjGen og(objid, generation); if (!this->m->obj_cache.count(og)) { // Store the object in the cache here so it gets cached // whether we first know the offset or whether we first know @@ -1987,12 +1952,11 @@ QPDF::objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph) } std::shared_ptr<QPDFObject> -QPDF::resolve(int objid, int generation) +QPDF::resolve(QPDFObjGen const& og) { // Check object cache before checking xref table. This allows us // to insert things into the object cache that don't actually // exist in the file. - QPDFObjGen og(objid, generation); if (this->m->resolving.count(og)) { // This can happen if an object references itself directly or // indirectly in some key that has to be resolved during @@ -2002,8 +1966,7 @@ QPDF::resolve(int objid, int generation) qpdf_e_damaged_pdf, "", this->m->file->getLastOffset(), - ("loop detected resolving object " + QUtil::int_to_string(objid) + - " " + QUtil::int_to_string(generation))); + ("loop detected resolving object " + og.unparse(' '))); return QPDF_Null::create(); } ResolveRecorder rr(this, og); @@ -2016,16 +1979,9 @@ QPDF::resolve(int objid, int generation) { qpdf_offset_t offset = entry.getOffset(); // Object stored in cache by readObjectAtOffset - int aobjid; - int ageneration; - QPDFObjectHandle oh = readObjectAtOffset( - true, - offset, - "", - objid, - generation, - aobjid, - ageneration); + QPDFObjGen a_og; + QPDFObjectHandle oh = + readObjectAtOffset(true, offset, "", og, a_og); } break; @@ -2039,8 +1995,7 @@ QPDF::resolve(int objid, int generation) this->m->file->getName(), "", 0, - ("object " + QUtil::int_to_string(objid) + "/" + - QUtil::int_to_string(generation) + + ("object " + og.unparse('/') + " has unexpected xref entry type")); } } catch (QPDFExc& e) { @@ -2050,8 +2005,7 @@ QPDF::resolve(int objid, int generation) qpdf_e_damaged_pdf, "", 0, - ("object " + QUtil::int_to_string(objid) + "/" + - QUtil::int_to_string(generation) + + ("object " + og.unparse('/') + ": error reading object: " + e.what())); } } @@ -2065,10 +2019,7 @@ QPDF::resolve(int objid, int generation) std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object); if (!result->hasDescription()) { - result->setDescription( - this, - ("object " + QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation))); + result->setDescription(this, ("object " + og.unparse(' '))); } return result; } @@ -2165,7 +2116,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number) (entry.getObjStreamNumber() == obj_stream_number)) { int offset = iter.second; input->seek(offset, SEEK_SET); - QPDFObjectHandle oh = readObject(input, "", obj, 0, true); + QPDFObjectHandle oh = readObject(input, "", og, true); this->m->obj_cache[og] = ObjCache( QPDFObjectHandle::ObjAccessor::getObject(oh), end_before_space, @@ -2187,48 +2138,46 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) QPDFObjGen next(max_objid + 1, 0); this->m->obj_cache[next] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); - return QPDFObjectHandle::Factory::newIndirect( - this, next.getObj(), next.getGen()); + return QPDFObjectHandle::Factory::newIndirect(this, next); } QPDFObjectHandle -QPDF::reserveObjectIfNotExists(int objid, int gen) +QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) { - QPDFObjGen og(objid, gen); if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) { - resolve(objid, gen); - replaceObject(objid, gen, QPDFObjectHandle::Factory::makeReserved()); + resolve(og); + replaceObject(og, QPDFObjectHandle::Factory::makeReserved()); } - return getObjectByID(objid, gen); + return getObjectByObjGen(og); } QPDFObjectHandle -QPDF::reserveStream(int objid, int gen) +QPDF::reserveStream(QPDFObjGen const& og) { return QPDFObjectHandle::Factory::newStream( - this, objid, gen, QPDFObjectHandle::newDictionary(), 0, 0); + this, og, QPDFObjectHandle::newDictionary(), 0, 0); } QPDFObjectHandle QPDF::getObjectByObjGen(QPDFObjGen const& og) { - return getObjectByID(og.getObj(), og.getGen()); + return QPDFObjectHandle::Factory::newIndirect(this, og); } QPDFObjectHandle QPDF::getObjectByID(int objid, int generation) { - return QPDFObjectHandle::Factory::newIndirect(this, objid, generation); + return getObjectByObjGen(QPDFObjGen(objid, generation)); } void -QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) +QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) { - replaceObject(og.getObj(), og.getGen(), oh); + replaceObject(QPDFObjGen(objid, generation), oh); } void -QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) +QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh) { if (oh.isIndirect()) { QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); @@ -2237,10 +2186,9 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh) } // Force new object to appear in the cache - resolve(objid, generation); + resolve(og); // Replace the object in the object cache - QPDFObjGen og(objid, generation); this->m->ever_replaced_objects = true; this->m->obj_cache[og] = ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1); @@ -2540,8 +2488,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) auto foreign_stream_data = std::make_shared<ForeignStreamData>( foreign_stream_qpdf->m->encp, foreign_stream_qpdf->m->file, - foreign.getObjectID(), - foreign.getGeneration(), + foreign.getObjGen(), stream->getOffset(), stream->getLength(), dict); @@ -2555,20 +2502,19 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign) } void -QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) +QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) { - swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen()); + swapObjects( + QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2)); } void -QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) +QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2) { // Force objects to be loaded into cache; then swap them in the // cache. - resolve(objid1, generation1); - resolve(objid2, generation2); - QPDFObjGen og1(objid1, generation1); - QPDFObjGen og2(objid2, generation2); + resolve(og1); + resolve(og2); ObjCache t = this->m->obj_cache[og1]; this->m->ever_replaced_objects = true; this->m->obj_cache[og1] = this->m->obj_cache[og2]; @@ -2752,8 +2698,7 @@ QPDF::pipeStreamData( std::shared_ptr<EncryptionParameters> encp, std::shared_ptr<InputSource> file, QPDF& qpdf_for_warning, - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle stream_dict, @@ -2764,14 +2709,7 @@ QPDF::pipeStreamData( std::vector<std::shared_ptr<Pipeline>> to_delete; if (encp->encrypted) { decryptStream( - encp, - file, - qpdf_for_warning, - pipeline, - objid, - generation, - stream_dict, - to_delete); + encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete); } bool success = false; @@ -2809,8 +2747,7 @@ QPDF::pipeStreamData( "", file->getLastOffset(), ("error decoding stream data for object " + - QUtil::int_to_string(objid) + " " + - QUtil::int_to_string(generation) + ": " + e.what()))); + og.unparse(' ') + ": " + e.what()))); if (will_retry) { qpdf_for_warning.warn( // line-break @@ -2836,8 +2773,7 @@ QPDF::pipeStreamData( bool QPDF::pipeStreamData( - int objid, - int generation, + QPDFObjGen const& og, qpdf_offset_t offset, size_t length, QPDFObjectHandle stream_dict, @@ -2849,8 +2785,7 @@ QPDF::pipeStreamData( this->m->encp, this->m->file, *this, - objid, - generation, + og, offset, length, stream_dict, @@ -2873,8 +2808,7 @@ QPDF::pipeForeignStreamData( foreign->encp, foreign->file, *this, - foreign->foreign_objid, - foreign->foreign_generation, + foreign->foreign_og, foreign->offset, foreign->length, foreign->local_dict, |