Commit f30a5eb05a8fe763184cd8167a4d4531909a34d5
1 parent
253d3aee
Move QPDF::read_xrefStream to QPDF::Xref_table
Showing
3 changed files
with
42 additions
and
52 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -759,19 +759,8 @@ class QPDF |
| 759 | 759 | |
| 760 | 760 | void parse(char const* password); |
| 761 | 761 | void inParse(bool); |
| 762 | - void setTrailer(QPDFObjectHandle obj); | |
| 763 | 762 | void read_xref(qpdf_offset_t offset); |
| 764 | 763 | bool resolveXRefTable(); |
| 765 | - qpdf_offset_t read_xrefStream(qpdf_offset_t offset); | |
| 766 | - qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); | |
| 767 | - std::pair<int, std::array<int, 3>> | |
| 768 | - processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged); | |
| 769 | - int processXRefSize( | |
| 770 | - QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged); | |
| 771 | - std::pair<int, std::vector<std::pair<int, int>>> processXRefIndex( | |
| 772 | - QPDFObjectHandle& dict, | |
| 773 | - int max_num_entries, | |
| 774 | - std::function<QPDFExc(std::string_view)> damaged); | |
| 775 | 764 | void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); |
| 776 | 765 | QPDFObjectHandle readTrailer(); |
| 777 | 766 | QPDFObjectHandle readObject(std::string const& description, QPDFObjGen og); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -526,15 +526,6 @@ QPDF::warn( |
| 526 | 526 | } |
| 527 | 527 | |
| 528 | 528 | void |
| 529 | -QPDF::setTrailer(QPDFObjectHandle obj) | |
| 530 | -{ | |
| 531 | - if (m->xref_table.trailer) { | |
| 532 | - return; | |
| 533 | - } | |
| 534 | - m->xref_table.trailer = obj; | |
| 535 | -} | |
| 536 | - | |
| 537 | -void | |
| 538 | 529 | QPDF::Xref_table::reconstruct(QPDFExc& e) |
| 539 | 530 | { |
| 540 | 531 | if (reconstructed) { |
| ... | ... | @@ -600,7 +591,7 @@ QPDF::Xref_table::reconstruct(QPDFExc& e) |
| 600 | 591 | if (!t.isDictionary()) { |
| 601 | 592 | // Oh well. It was worth a try. |
| 602 | 593 | } else { |
| 603 | - qpdf.setTrailer(t); | |
| 594 | + trailer = t; | |
| 604 | 595 | } |
| 605 | 596 | m->file->seek(pos, SEEK_SET); |
| 606 | 597 | } |
| ... | ... | @@ -725,7 +716,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) |
| 725 | 716 | } |
| 726 | 717 | xref_offset = m->xref_table.read_table(xref_offset + skip); |
| 727 | 718 | } else { |
| 728 | - xref_offset = read_xrefStream(xref_offset); | |
| 719 | + xref_offset = m->xref_table.read_stream(xref_offset); | |
| 729 | 720 | } |
| 730 | 721 | if (visited.count(xref_offset) != 0) { |
| 731 | 722 | QTC::TC("qpdf", "QPDF xref loop"); |
| ... | ... | @@ -1028,7 +1019,7 @@ QPDF::Xref_table::read_table(qpdf_offset_t xref_offset) |
| 1028 | 1019 | if (cur_trailer.getKey("/XRefStm").isInteger()) { |
| 1029 | 1020 | // Read the xref stream but disregard any return value -- we'll use our trailer's |
| 1030 | 1021 | // /Prev key instead of the xref stream's. |
| 1031 | - (void)qpdf.read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue()); | |
| 1022 | + (void)read_stream(cur_trailer.getKey("/XRefStm").getIntValue()); | |
| 1032 | 1023 | } else { |
| 1033 | 1024 | throw qpdf.damagedPDF("xref stream", xref_offset, "invalid /XRefStm"); |
| 1034 | 1025 | } |
| ... | ... | @@ -1049,34 +1040,35 @@ QPDF::Xref_table::read_table(qpdf_offset_t xref_offset) |
| 1049 | 1040 | |
| 1050 | 1041 | // Read a single cross-reference stream. |
| 1051 | 1042 | qpdf_offset_t |
| 1052 | -QPDF::read_xrefStream(qpdf_offset_t xref_offset) | |
| 1043 | +QPDF::Xref_table::read_stream(qpdf_offset_t xref_offset) | |
| 1053 | 1044 | { |
| 1054 | - if (!m->xref_table.ignore_streams) { | |
| 1045 | + if (!ignore_streams) { | |
| 1055 | 1046 | QPDFObjGen x_og; |
| 1056 | 1047 | QPDFObjectHandle xref_obj; |
| 1057 | 1048 | try { |
| 1058 | - xref_obj = | |
| 1059 | - readObjectAtOffset(false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og, true); | |
| 1049 | + xref_obj = qpdf.readObjectAtOffset( | |
| 1050 | + false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og, true); | |
| 1060 | 1051 | } catch (QPDFExc&) { |
| 1061 | 1052 | // ignore -- report error below |
| 1062 | 1053 | } |
| 1063 | 1054 | if (xref_obj.isStreamOfType("/XRef")) { |
| 1064 | 1055 | QTC::TC("qpdf", "QPDF found xref stream"); |
| 1065 | - return processXRefStream(xref_offset, xref_obj); | |
| 1056 | + return process_stream(xref_offset, xref_obj); | |
| 1066 | 1057 | } |
| 1067 | 1058 | } |
| 1068 | 1059 | |
| 1069 | 1060 | QTC::TC("qpdf", "QPDF can't find xref"); |
| 1070 | - throw damagedPDF("", xref_offset, "xref not found"); | |
| 1061 | + throw qpdf.damagedPDF("", xref_offset, "xref not found"); | |
| 1071 | 1062 | return 0; // unreachable |
| 1072 | 1063 | } |
| 1073 | 1064 | |
| 1074 | 1065 | // Return the entry size of the xref stream and the processed W array. |
| 1075 | 1066 | std::pair<int, std::array<int, 3>> |
| 1076 | -QPDF::processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged) | |
| 1067 | +QPDF::Xref_table::process_W( | |
| 1068 | + QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged) | |
| 1077 | 1069 | { |
| 1078 | 1070 | auto W_obj = dict.getKey("/W"); |
| 1079 | - if (!(W_obj.isArray() && (W_obj.getArrayNItems() >= 3) && W_obj.getArrayItem(0).isInteger() && | |
| 1071 | + if (!(W_obj.isArray() && W_obj.getArrayNItems() >= 3 && W_obj.getArrayItem(0).isInteger() && | |
| 1080 | 1072 | W_obj.getArrayItem(1).isInteger() && W_obj.getArrayItem(2).isInteger())) { |
| 1081 | 1073 | throw damaged("Cross-reference stream does not have a proper /W key"); |
| 1082 | 1074 | } |
| ... | ... | @@ -1103,7 +1095,7 @@ QPDF::processXRefW(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_vie |
| 1103 | 1095 | |
| 1104 | 1096 | // Validate Size key and return the maximum number of entries that the xref stream can contain. |
| 1105 | 1097 | int |
| 1106 | -QPDF::processXRefSize( | |
| 1098 | +QPDF::Xref_table::process_Size( | |
| 1107 | 1099 | QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged) |
| 1108 | 1100 | { |
| 1109 | 1101 | // Number of entries is limited by the highest possible object id and stream size. |
| ... | ... | @@ -1127,7 +1119,7 @@ QPDF::processXRefSize( |
| 1127 | 1119 | |
| 1128 | 1120 | // Return the number of entries of the xref stream and the processed Index array. |
| 1129 | 1121 | std::pair<int, std::vector<std::pair<int, int>>> |
| 1130 | -QPDF::processXRefIndex( | |
| 1122 | +QPDF::Xref_table::process_Index( | |
| 1131 | 1123 | QPDFObjectHandle& dict, int max_num_entries, std::function<QPDFExc(std::string_view)> damaged) |
| 1132 | 1124 | { |
| 1133 | 1125 | auto size = dict.getKey("/Size").getIntValueAsInt(); |
| ... | ... | @@ -1194,17 +1186,17 @@ QPDF::processXRefIndex( |
| 1194 | 1186 | } |
| 1195 | 1187 | |
| 1196 | 1188 | qpdf_offset_t |
| 1197 | -QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) | |
| 1189 | +QPDF::Xref_table::process_stream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) | |
| 1198 | 1190 | { |
| 1199 | 1191 | auto damaged = [this, xref_offset](std::string_view msg) -> QPDFExc { |
| 1200 | - return damagedPDF("xref stream", xref_offset, msg.data()); | |
| 1192 | + return qpdf.damagedPDF("xref stream", xref_offset, msg.data()); | |
| 1201 | 1193 | }; |
| 1202 | 1194 | |
| 1203 | 1195 | auto dict = xref_obj.getDict(); |
| 1204 | 1196 | |
| 1205 | - auto [entry_size, W] = processXRefW(dict, damaged); | |
| 1206 | - int max_num_entries = processXRefSize(dict, entry_size, damaged); | |
| 1207 | - auto [num_entries, indx] = processXRefIndex(dict, max_num_entries, damaged); | |
| 1197 | + auto [entry_size, W] = process_W(dict, damaged); | |
| 1198 | + int max_num_entries = process_Size(dict, entry_size, damaged); | |
| 1199 | + auto [num_entries, indx] = process_Index(dict, max_num_entries, damaged); | |
| 1208 | 1200 | |
| 1209 | 1201 | std::shared_ptr<Buffer> bp = xref_obj.getStreamData(qpdf_dl_specialized); |
| 1210 | 1202 | size_t actual_size = bp->getSize(); |
| ... | ... | @@ -1217,7 +1209,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) |
| 1217 | 1209 | if (expected_size > actual_size) { |
| 1218 | 1210 | throw x; |
| 1219 | 1211 | } else { |
| 1220 | - warn(x); | |
| 1212 | + qpdf.warn(x); | |
| 1221 | 1213 | } |
| 1222 | 1214 | } |
| 1223 | 1215 | |
| ... | ... | @@ -1246,33 +1238,33 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) |
| 1246 | 1238 | // object record, in which case the generation number appears as the third field. |
| 1247 | 1239 | if (saw_first_compressed_object) { |
| 1248 | 1240 | if (fields[0] != 2) { |
| 1249 | - m->xref_table.uncompressed_after_compressed = true; | |
| 1241 | + uncompressed_after_compressed = true; | |
| 1250 | 1242 | } |
| 1251 | 1243 | } else if (fields[0] == 2) { |
| 1252 | 1244 | saw_first_compressed_object = true; |
| 1253 | 1245 | } |
| 1254 | 1246 | if (obj == 0) { |
| 1255 | 1247 | // This is needed by checkLinearization() |
| 1256 | - m->xref_table.first_item_offset = xref_offset; | |
| 1248 | + first_item_offset = xref_offset; | |
| 1257 | 1249 | } else if (fields[0] == 0) { |
| 1258 | 1250 | // Ignore fields[2], which we don't care about in this case. This works around the |
| 1259 | 1251 | // issue of some PDF files that put invalid values, like -1, here for deleted |
| 1260 | 1252 | // objects. |
| 1261 | - m->xref_table.insert_free(QPDFObjGen(obj, 0)); | |
| 1253 | + insert_free(QPDFObjGen(obj, 0)); | |
| 1262 | 1254 | } else { |
| 1263 | - m->xref_table.insert(obj, toI(fields[0]), fields[1], toI(fields[2])); | |
| 1255 | + insert(obj, toI(fields[0]), fields[1], toI(fields[2])); | |
| 1264 | 1256 | } |
| 1265 | 1257 | ++obj; |
| 1266 | 1258 | } |
| 1267 | 1259 | } |
| 1268 | 1260 | |
| 1269 | - if (!m->xref_table.trailer) { | |
| 1270 | - setTrailer(dict); | |
| 1261 | + if (!trailer) { | |
| 1262 | + trailer = dict; | |
| 1271 | 1263 | } |
| 1272 | 1264 | |
| 1273 | 1265 | if (dict.hasKey("/Prev")) { |
| 1274 | 1266 | if (!dict.getKey("/Prev").isInteger()) { |
| 1275 | - throw damagedPDF( | |
| 1267 | + throw qpdf.damagedPDF( | |
| 1276 | 1268 | "xref stream", "/Prev key in xref stream dictionary is not an integer"); |
| 1277 | 1269 | } |
| 1278 | 1270 | QTC::TC("qpdf", "QPDF prev key in xref stream dictionary"); |
| ... | ... | @@ -1378,8 +1370,7 @@ QPDF::showXRefTable() |
| 1378 | 1370 | break; |
| 1379 | 1371 | |
| 1380 | 1372 | default: |
| 1381 | - throw std::logic_error("unknown cross-reference table type while" | |
| 1382 | - " showing xref_table"); | |
| 1373 | + throw std::logic_error("unknown cross-reference table type while showing xref_table"); | |
| 1383 | 1374 | break; |
| 1384 | 1375 | } |
| 1385 | 1376 | m->log->info("\n"); | ... | ... |
libqpdf/qpdf/QPDF_private.hh
| ... | ... | @@ -13,10 +13,7 @@ class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry> |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | qpdf_offset_t read_table(qpdf_offset_t offset); |
| 16 | - | |
| 17 | - void insert_reconstructed(int obj, qpdf_offset_t f1, int f2); | |
| 18 | - void insert(int obj, int f0, qpdf_offset_t f1, int f2); | |
| 19 | - void insert_free(QPDFObjGen); | |
| 16 | + qpdf_offset_t read_stream(qpdf_offset_t offset); | |
| 20 | 17 | |
| 21 | 18 | void reconstruct(QPDFExc& e); |
| 22 | 19 | |
| ... | ... | @@ -38,6 +35,19 @@ class QPDF::Xref_table: public std::map<QPDFObjGen, QPDFXRefEntry> |
| 38 | 35 | bool parse_first(std::string const& line, int& obj, int& num, int& bytes); |
| 39 | 36 | bool read_entry(qpdf_offset_t& f1, int& f2, char& type); |
| 40 | 37 | bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type); |
| 38 | + qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); | |
| 39 | + std::pair<int, std::array<int, 3>> | |
| 40 | + process_W(QPDFObjectHandle& dict, std::function<QPDFExc(std::string_view)> damaged); | |
| 41 | + int process_Size( | |
| 42 | + QPDFObjectHandle& dict, int entry_size, std::function<QPDFExc(std::string_view)> damaged); | |
| 43 | + std::pair<int, std::vector<std::pair<int, int>>> process_Index( | |
| 44 | + QPDFObjectHandle& dict, | |
| 45 | + int max_num_entries, | |
| 46 | + std::function<QPDFExc(std::string_view)> damaged); | |
| 47 | + | |
| 48 | + void insert_reconstructed(int obj, qpdf_offset_t f1, int f2); | |
| 49 | + void insert(int obj, int f0, qpdf_offset_t f1, int f2); | |
| 50 | + void insert_free(QPDFObjGen); | |
| 41 | 51 | |
| 42 | 52 | QPDFExc |
| 43 | 53 | damaged_pdf(std::string const& msg) | ... | ... |