mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Move QPDF::read_xref to QPDF::Xref_table
This commit is contained in:
parent
f30a5eb05a
commit
a4db9b3149
@ -759,7 +759,6 @@ class QPDF
|
||||
|
||||
void parse(char const* password);
|
||||
void inParse(bool);
|
||||
void read_xref(qpdf_offset_t offset);
|
||||
bool resolveXRefTable();
|
||||
void setLastObjectDescription(std::string const& description, QPDFObjGen const& og);
|
||||
QPDFObjectHandle readTrailer();
|
||||
|
@ -468,7 +468,7 @@ QPDF::parse(char const* password)
|
||||
throw damagedPDF("", 0, "can't find startxref");
|
||||
}
|
||||
try {
|
||||
read_xref(xref_offset);
|
||||
m->xref_table.read(xref_offset);
|
||||
} catch (QPDFExc&) {
|
||||
throw;
|
||||
} catch (std::exception& e) {
|
||||
@ -625,7 +625,7 @@ QPDF::Xref_table::reconstruct(QPDFExc& e)
|
||||
}
|
||||
if (max_offset > 0) {
|
||||
try {
|
||||
qpdf.read_xref(max_offset);
|
||||
read(max_offset);
|
||||
} catch (std::exception&) {
|
||||
throw damaged_pdf(
|
||||
"error decoding candidate xref stream while recovering damaged file");
|
||||
@ -664,8 +664,10 @@ QPDF::Xref_table::reconstruct(QPDFExc& e)
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::read_xref(qpdf_offset_t xref_offset)
|
||||
QPDF::Xref_table::read(qpdf_offset_t xref_offset)
|
||||
{
|
||||
auto* m = qpdf.m.get();
|
||||
|
||||
std::map<int, int> free_table;
|
||||
std::set<qpdf_offset_t> visited;
|
||||
while (xref_offset) {
|
||||
@ -700,7 +702,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
|
||||
if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) {
|
||||
if (skipped_space) {
|
||||
QTC::TC("qpdf", "QPDF xref skipped space");
|
||||
warn(damagedPDF("", 0, "extraneous whitespace seen before xref"));
|
||||
warn_damaged("extraneous whitespace seen before xref");
|
||||
}
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
@ -714,46 +716,43 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
|
||||
while (QUtil::is_space(buf[skip])) {
|
||||
++skip;
|
||||
}
|
||||
xref_offset = m->xref_table.read_table(xref_offset + skip);
|
||||
xref_offset = read_table(xref_offset + skip);
|
||||
} else {
|
||||
xref_offset = m->xref_table.read_stream(xref_offset);
|
||||
xref_offset = read_stream(xref_offset);
|
||||
}
|
||||
if (visited.count(xref_offset) != 0) {
|
||||
QTC::TC("qpdf", "QPDF xref loop");
|
||||
throw damagedPDF("", 0, "loop detected following xref tables");
|
||||
throw damaged_pdf("loop detected following xref tables");
|
||||
}
|
||||
}
|
||||
|
||||
if (!m->xref_table.trailer) {
|
||||
throw damagedPDF("", 0, "unable to find trailer while reading xref");
|
||||
if (!trailer) {
|
||||
throw damaged_pdf("unable to find trailer while reading xref");
|
||||
}
|
||||
int size = m->xref_table.trailer.getKey("/Size").getIntValueAsInt();
|
||||
int size = trailer.getKey("/Size").getIntValueAsInt();
|
||||
int max_obj = 0;
|
||||
if (!m->xref_table.empty()) {
|
||||
max_obj = m->xref_table.rbegin()->first.getObj();
|
||||
if (!empty()) {
|
||||
max_obj = rbegin()->first.getObj();
|
||||
}
|
||||
if (!m->xref_table.deleted_objects.empty()) {
|
||||
max_obj = std::max(max_obj, *(m->xref_table.deleted_objects.rbegin()));
|
||||
if (!deleted_objects.empty()) {
|
||||
max_obj = std::max(max_obj, *deleted_objects.rbegin());
|
||||
}
|
||||
if ((size < 1) || (size - 1 != max_obj)) {
|
||||
QTC::TC("qpdf", "QPDF xref size mismatch");
|
||||
warn(damagedPDF(
|
||||
"",
|
||||
0,
|
||||
("reported number of objects (" + std::to_string(size) +
|
||||
") is not one plus the highest object number (" + std::to_string(max_obj) + ")")));
|
||||
warn_damaged("reported number of objects (" + std::to_string(size) +
|
||||
") is not one plus the highest object number (" + std::to_string(max_obj) + ")");
|
||||
}
|
||||
|
||||
// We no longer need the deleted_objects table, so go ahead and clear it out to make sure we
|
||||
// never depend on its being set.
|
||||
m->xref_table.deleted_objects.clear();
|
||||
deleted_objects.clear();
|
||||
|
||||
// Make sure we keep only the highest generation for any object.
|
||||
QPDFObjGen last_og{-1, 0};
|
||||
for (auto const& item: m->xref_table) {
|
||||
for (auto const& item: *this) {
|
||||
auto id = item.first.getObj();
|
||||
if (id == last_og.getObj() && id > 0) {
|
||||
removeObject(last_og);
|
||||
qpdf.removeObject(last_og);
|
||||
}
|
||||
last_og = item.first;
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry>
|
||||
{
|
||||
}
|
||||
|
||||
qpdf_offset_t read_table(qpdf_offset_t offset);
|
||||
qpdf_offset_t read_stream(qpdf_offset_t offset);
|
||||
|
||||
void read(qpdf_offset_t offset);
|
||||
void reconstruct(QPDFExc& e);
|
||||
|
||||
QPDFObjectHandle trailer;
|
||||
@ -32,9 +30,14 @@ class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry>
|
||||
qpdf_offset_t first_item_offset{0}; // actual value from file
|
||||
|
||||
private:
|
||||
// Methods to parse tables
|
||||
qpdf_offset_t read_table(qpdf_offset_t offset);
|
||||
bool parse_first(std::string const& line, int& obj, int& num, int& bytes);
|
||||
bool read_entry(qpdf_offset_t& f1, int& f2, char& type);
|
||||
bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type);
|
||||
|
||||
// Methods to parse streams
|
||||
qpdf_offset_t read_stream(qpdf_offset_t offset);
|
||||
qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
|
||||
std::pair<int, std::array<int, 3>>
|
||||
process_W(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged);
|
||||
@ -45,6 +48,7 @@ class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry>
|
||||
int max_num_entries,
|
||||
std::function<QPDFExc(std::string_view)> damaged);
|
||||
|
||||
// Methods to insert table entries
|
||||
void insert_reconstructed(int obj, qpdf_offset_t f1, int f2);
|
||||
void insert(int obj, int f0, qpdf_offset_t f1, int f2);
|
||||
void insert_free(QPDFObjGen);
|
||||
|
Loading…
Reference in New Issue
Block a user