Commit 774584163ff3d310e7c932e2a6f63b590cb736ac
1 parent
3101955a
Add ExtensionLevel support to version handling
All version operations are now fully aware of extension levels.
Showing
92 changed files
with
1423 additions
and
30 deletions
include/qpdf/QPDF.hh
| @@ -144,6 +144,8 @@ class QPDF | @@ -144,6 +144,8 @@ class QPDF | ||
| 144 | QPDF_DLL | 144 | QPDF_DLL |
| 145 | std::string getPDFVersion() const; | 145 | std::string getPDFVersion() const; |
| 146 | QPDF_DLL | 146 | QPDF_DLL |
| 147 | + int getExtensionLevel(); | ||
| 148 | + QPDF_DLL | ||
| 147 | QPDFObjectHandle getTrailer(); | 149 | QPDFObjectHandle getTrailer(); |
| 148 | QPDF_DLL | 150 | QPDF_DLL |
| 149 | QPDFObjectHandle getRoot(); | 151 | QPDFObjectHandle getRoot(); |
include/qpdf/QPDFWriter.hh
| @@ -153,6 +153,8 @@ class QPDFWriter | @@ -153,6 +153,8 @@ class QPDFWriter | ||
| 153 | // streams are used. | 153 | // streams are used. |
| 154 | QPDF_DLL | 154 | QPDF_DLL |
| 155 | void setMinimumPDFVersion(std::string const&); | 155 | void setMinimumPDFVersion(std::string const&); |
| 156 | + QPDF_DLL | ||
| 157 | + void setMinimumPDFVersion(std::string const&, int extension_level); | ||
| 156 | 158 | ||
| 157 | // Force the PDF version of the output file to be a given version. | 159 | // Force the PDF version of the output file to be a given version. |
| 158 | // Use of this function may create PDF files that will not work | 160 | // Use of this function may create PDF files that will not work |
| @@ -171,6 +173,8 @@ class QPDFWriter | @@ -171,6 +173,8 @@ class QPDFWriter | ||
| 171 | // object streams. | 173 | // object streams. |
| 172 | QPDF_DLL | 174 | QPDF_DLL |
| 173 | void forcePDFVersion(std::string const&); | 175 | void forcePDFVersion(std::string const&); |
| 176 | + QPDF_DLL | ||
| 177 | + void forcePDFVersion(std::string const&, int extension_level); | ||
| 174 | 178 | ||
| 175 | // Provide additional text to insert in the PDF file somewhere | 179 | // Provide additional text to insert in the PDF file somewhere |
| 176 | // near the beginning of the file. This can be used to add | 180 | // near the beginning of the file. This can be used to add |
| @@ -251,6 +255,7 @@ class QPDFWriter | @@ -251,6 +255,7 @@ class QPDFWriter | ||
| 251 | static int const f_stream = 1 << 0; | 255 | static int const f_stream = 1 << 0; |
| 252 | static int const f_filtered = 1 << 1; | 256 | static int const f_filtered = 1 << 1; |
| 253 | static int const f_in_ostream = 1 << 2; | 257 | static int const f_in_ostream = 1 << 2; |
| 258 | + static int const f_in_extensions = 1 << 3; | ||
| 254 | 259 | ||
| 255 | enum trailer_e { t_normal, t_lin_first, t_lin_second }; | 260 | enum trailer_e { t_normal, t_lin_first, t_lin_second }; |
| 256 | 261 | ||
| @@ -286,7 +291,8 @@ class QPDFWriter | @@ -286,7 +291,8 @@ class QPDFWriter | ||
| 286 | char const* user_password, char const* owner_password, | 291 | char const* user_password, char const* owner_password, |
| 287 | bool allow_accessibility, bool allow_extract, | 292 | bool allow_accessibility, bool allow_extract, |
| 288 | qpdf_r3_print_e print, qpdf_r3_modify_e modify); | 293 | qpdf_r3_print_e print, qpdf_r3_modify_e modify); |
| 289 | - void disableIncompatibleEncryption(int major, int minor); | 294 | + void disableIncompatibleEncryption(int major, int minor, |
| 295 | + int extension_level); | ||
| 290 | void parseVersion(std::string const& version, int& major, int& minor) const; | 296 | void parseVersion(std::string const& version, int& major, int& minor) const; |
| 291 | int compareVersions(int major1, int minor1, int major2, int minor2) const; | 297 | int compareVersions(int major1, int minor1, int major2, int minor2) const; |
| 292 | void setEncryptionParameters( | 298 | void setEncryptionParameters( |
| @@ -375,8 +381,12 @@ class QPDFWriter | @@ -375,8 +381,12 @@ class QPDFWriter | ||
| 375 | 381 | ||
| 376 | std::string id1; // for /ID key of | 382 | std::string id1; // for /ID key of |
| 377 | std::string id2; // trailer dictionary | 383 | std::string id2; // trailer dictionary |
| 384 | + std::string final_pdf_version; | ||
| 385 | + int final_extension_level; | ||
| 378 | std::string min_pdf_version; | 386 | std::string min_pdf_version; |
| 387 | + int min_extension_level; | ||
| 379 | std::string forced_pdf_version; | 388 | std::string forced_pdf_version; |
| 389 | + int forced_extension_level; | ||
| 380 | std::string extra_header_text; | 390 | std::string extra_header_text; |
| 381 | int encryption_dict_objid; | 391 | int encryption_dict_objid; |
| 382 | std::string cur_data_key; | 392 | std::string cur_data_key; |
libqpdf/QPDF.cc
| @@ -1872,6 +1872,30 @@ QPDF::getPDFVersion() const | @@ -1872,6 +1872,30 @@ QPDF::getPDFVersion() const | ||
| 1872 | return this->pdf_version; | 1872 | return this->pdf_version; |
| 1873 | } | 1873 | } |
| 1874 | 1874 | ||
| 1875 | +int | ||
| 1876 | +QPDF::getExtensionLevel() | ||
| 1877 | +{ | ||
| 1878 | + int result = 0; | ||
| 1879 | + QPDFObjectHandle obj = getRoot(); | ||
| 1880 | + if (obj.hasKey("/Extensions")) | ||
| 1881 | + { | ||
| 1882 | + obj = obj.getKey("/Extensions"); | ||
| 1883 | + if (obj.isDictionary() && obj.hasKey("/ADBE")) | ||
| 1884 | + { | ||
| 1885 | + obj = obj.getKey("/ADBE"); | ||
| 1886 | + if (obj.isDictionary() && obj.hasKey("/ExtensionLevel")) | ||
| 1887 | + { | ||
| 1888 | + obj = obj.getKey("/ExtensionLevel"); | ||
| 1889 | + if (obj.isInteger()) | ||
| 1890 | + { | ||
| 1891 | + result = obj.getIntValue(); | ||
| 1892 | + } | ||
| 1893 | + } | ||
| 1894 | + } | ||
| 1895 | + } | ||
| 1896 | + return result; | ||
| 1897 | +} | ||
| 1898 | + | ||
| 1875 | QPDFObjectHandle | 1899 | QPDFObjectHandle |
| 1876 | QPDF::getTrailer() | 1900 | QPDF::getTrailer() |
| 1877 | { | 1901 | { |
libqpdf/QPDFWriter.cc
| @@ -64,6 +64,9 @@ QPDFWriter::init() | @@ -64,6 +64,9 @@ QPDFWriter::init() | ||
| 64 | object_stream_mode = qpdf_o_preserve; | 64 | object_stream_mode = qpdf_o_preserve; |
| 65 | encrypt_metadata = true; | 65 | encrypt_metadata = true; |
| 66 | encrypt_use_aes = false; | 66 | encrypt_use_aes = false; |
| 67 | + min_extension_level = 0; | ||
| 68 | + final_extension_level = 0; | ||
| 69 | + forced_extension_level = 0; | ||
| 67 | encryption_dict_objid = 0; | 70 | encryption_dict_objid = 0; |
| 68 | next_objid = 1; | 71 | next_objid = 1; |
| 69 | cur_stream_length_id = 0; | 72 | cur_stream_length_id = 0; |
| @@ -170,10 +173,19 @@ QPDFWriter::setQDFMode(bool val) | @@ -170,10 +173,19 @@ QPDFWriter::setQDFMode(bool val) | ||
| 170 | void | 173 | void |
| 171 | QPDFWriter::setMinimumPDFVersion(std::string const& version) | 174 | QPDFWriter::setMinimumPDFVersion(std::string const& version) |
| 172 | { | 175 | { |
| 176 | + setMinimumPDFVersion(version, 0); | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +void | ||
| 180 | +QPDFWriter::setMinimumPDFVersion(std::string const& version, | ||
| 181 | + int extension_level) | ||
| 182 | +{ | ||
| 173 | bool set_version = false; | 183 | bool set_version = false; |
| 184 | + bool set_extension_level = false; | ||
| 174 | if (this->min_pdf_version.empty()) | 185 | if (this->min_pdf_version.empty()) |
| 175 | { | 186 | { |
| 176 | set_version = true; | 187 | set_version = true; |
| 188 | + set_extension_level = true; | ||
| 177 | } | 189 | } |
| 178 | else | 190 | else |
| 179 | { | 191 | { |
| @@ -183,10 +195,22 @@ QPDFWriter::setMinimumPDFVersion(std::string const& version) | @@ -183,10 +195,22 @@ QPDFWriter::setMinimumPDFVersion(std::string const& version) | ||
| 183 | int min_minor = 0; | 195 | int min_minor = 0; |
| 184 | parseVersion(version, old_major, old_minor); | 196 | parseVersion(version, old_major, old_minor); |
| 185 | parseVersion(this->min_pdf_version, min_major, min_minor); | 197 | parseVersion(this->min_pdf_version, min_major, min_minor); |
| 186 | - if (compareVersions(old_major, old_minor, min_major, min_minor) > 0) | 198 | + int compare = compareVersions( |
| 199 | + old_major, old_minor, min_major, min_minor); | ||
| 200 | + if (compare > 0) | ||
| 187 | { | 201 | { |
| 188 | - QTC::TC("qpdf", "QPDFWriter increasing minimum version"); | 202 | + QTC::TC("qpdf", "QPDFWriter increasing minimum version", |
| 203 | + extension_level == 0 ? 0 : 1); | ||
| 189 | set_version = true; | 204 | set_version = true; |
| 205 | + set_extension_level = true; | ||
| 206 | + } | ||
| 207 | + else if (compare == 0) | ||
| 208 | + { | ||
| 209 | + if (extension_level > this->min_extension_level) | ||
| 210 | + { | ||
| 211 | + QTC::TC("qpdf", "QPDFWriter increasing extension level"); | ||
| 212 | + set_extension_level = true; | ||
| 213 | + } | ||
| 190 | } | 214 | } |
| 191 | } | 215 | } |
| 192 | 216 | ||
| @@ -194,12 +218,24 @@ QPDFWriter::setMinimumPDFVersion(std::string const& version) | @@ -194,12 +218,24 @@ QPDFWriter::setMinimumPDFVersion(std::string const& version) | ||
| 194 | { | 218 | { |
| 195 | this->min_pdf_version = version; | 219 | this->min_pdf_version = version; |
| 196 | } | 220 | } |
| 221 | + if (set_extension_level) | ||
| 222 | + { | ||
| 223 | + this->min_extension_level = extension_level; | ||
| 224 | + } | ||
| 197 | } | 225 | } |
| 198 | 226 | ||
| 199 | void | 227 | void |
| 200 | QPDFWriter::forcePDFVersion(std::string const& version) | 228 | QPDFWriter::forcePDFVersion(std::string const& version) |
| 201 | { | 229 | { |
| 230 | + forcePDFVersion(version, 0); | ||
| 231 | +} | ||
| 232 | + | ||
| 233 | +void | ||
| 234 | +QPDFWriter::forcePDFVersion(std::string const& version, | ||
| 235 | + int extension_level) | ||
| 236 | +{ | ||
| 202 | this->forced_pdf_version = version; | 237 | this->forced_pdf_version = version; |
| 238 | + this->forced_extension_level = extension_level; | ||
| 203 | } | 239 | } |
| 204 | 240 | ||
| 205 | void | 241 | void |
| @@ -476,7 +512,8 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) | @@ -476,7 +512,8 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) | ||
| 476 | } | 512 | } |
| 477 | 513 | ||
| 478 | void | 514 | void |
| 479 | -QPDFWriter::disableIncompatibleEncryption(int major, int minor) | 515 | +QPDFWriter::disableIncompatibleEncryption(int major, int minor, |
| 516 | + int extension_level) | ||
| 480 | { | 517 | { |
| 481 | if (! this->encrypted) | 518 | if (! this->encrypted) |
| 482 | { | 519 | { |
| @@ -513,6 +550,15 @@ QPDFWriter::disableIncompatibleEncryption(int major, int minor) | @@ -513,6 +550,15 @@ QPDFWriter::disableIncompatibleEncryption(int major, int minor) | ||
| 513 | disable = true; | 550 | disable = true; |
| 514 | } | 551 | } |
| 515 | } | 552 | } |
| 553 | + else if ((compareVersions(major, minor, 1, 7) < 0) || | ||
| 554 | + ((compareVersions(major, minor, 1, 7) == 0) && | ||
| 555 | + extension_level < 3)) | ||
| 556 | + { | ||
| 557 | + if ((V >= 5) || (R >= 5)) | ||
| 558 | + { | ||
| 559 | + disable = true; | ||
| 560 | + } | ||
| 561 | + } | ||
| 516 | } | 562 | } |
| 517 | if (disable) | 563 | if (disable) |
| 518 | { | 564 | { |
| @@ -584,15 +630,26 @@ QPDFWriter::setEncryptionParametersInternal( | @@ -584,15 +630,26 @@ QPDFWriter::setEncryptionParametersInternal( | ||
| 584 | encryption_dictionary["/P"] = QUtil::int_to_string(P); | 630 | encryption_dictionary["/P"] = QUtil::int_to_string(P); |
| 585 | encryption_dictionary["/O"] = QPDF_String(O).unparse(true); | 631 | encryption_dictionary["/O"] = QPDF_String(O).unparse(true); |
| 586 | encryption_dictionary["/U"] = QPDF_String(U).unparse(true); | 632 | encryption_dictionary["/U"] = QPDF_String(U).unparse(true); |
| 587 | - setMinimumPDFVersion("1.3"); | ||
| 588 | - if (R == 3) | 633 | + if (V >= 5) |
| 589 | { | 634 | { |
| 590 | setMinimumPDFVersion("1.4"); | 635 | setMinimumPDFVersion("1.4"); |
| 591 | } | 636 | } |
| 592 | - else if (R >= 4) | 637 | + if (R >= 5) |
| 638 | + { | ||
| 639 | + setMinimumPDFVersion("1.7", 3); | ||
| 640 | + } | ||
| 641 | + else if (R == 4) | ||
| 593 | { | 642 | { |
| 594 | setMinimumPDFVersion(this->encrypt_use_aes ? "1.6" : "1.5"); | 643 | setMinimumPDFVersion(this->encrypt_use_aes ? "1.6" : "1.5"); |
| 595 | } | 644 | } |
| 645 | + else if (R == 3) | ||
| 646 | + { | ||
| 647 | + setMinimumPDFVersion("1.4"); | ||
| 648 | + } | ||
| 649 | + else | ||
| 650 | + { | ||
| 651 | + setMinimumPDFVersion("1.3"); | ||
| 652 | + } | ||
| 596 | 653 | ||
| 597 | if ((R >= 4) && (! encrypt_metadata)) | 654 | if ((R >= 4) && (! encrypt_metadata)) |
| 598 | { | 655 | { |
| @@ -1005,7 +1062,7 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | @@ -1005,7 +1062,7 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | ||
| 1005 | unsigned int flags, size_t stream_length, | 1062 | unsigned int flags, size_t stream_length, |
| 1006 | bool compress) | 1063 | bool compress) |
| 1007 | { | 1064 | { |
| 1008 | - unsigned int child_flags = flags & ~f_stream; | 1065 | + unsigned int child_flags = flags & ~f_stream & ~f_in_extensions; |
| 1009 | 1066 | ||
| 1010 | std::string indent; | 1067 | std::string indent; |
| 1011 | for (int i = 0; i < level; ++i) | 1068 | for (int i = 0; i < level; ++i) |
| @@ -1037,8 +1094,143 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | @@ -1037,8 +1094,143 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | ||
| 1037 | } | 1094 | } |
| 1038 | else if (object.isDictionary()) | 1095 | else if (object.isDictionary()) |
| 1039 | { | 1096 | { |
| 1097 | + // Handle special cases for specific dictionaries. | ||
| 1098 | + | ||
| 1099 | + // Extensions dictionaries are complicated. We have one of | ||
| 1100 | + // several cases: | ||
| 1101 | + // | ||
| 1102 | + // * We need ADBE | ||
| 1103 | + // - We already have Extensions | ||
| 1104 | + // - If it has the right ADBE, preserve it | ||
| 1105 | + // - Otherwise, replace ADBE | ||
| 1106 | + // - We don't have Extensions: create one from scratch | ||
| 1107 | + // * We don't want ADBE | ||
| 1108 | + // - We already have Extensions | ||
| 1109 | + // - If it only has ADBE, remove it | ||
| 1110 | + // - If it has other things, keep those and remove ADBE | ||
| 1111 | + // - We have no extensions: no action required | ||
| 1112 | + // | ||
| 1113 | + // We may be in the root dictionary, or we may be inside the | ||
| 1114 | + // extensions dictionary itself. The latter is determined by | ||
| 1115 | + // the presence of the f_in_extensions flag. | ||
| 1116 | + | ||
| 1117 | + bool is_root = false; | ||
| 1118 | + bool have_extensions_other = false; | ||
| 1119 | + bool have_extensions_adbe = false; | ||
| 1120 | + | ||
| 1121 | + QPDFObjectHandle extensions; | ||
| 1122 | + if (object.getObjectID() == pdf.getRoot().getObjectID()) | ||
| 1123 | + { | ||
| 1124 | + is_root = true; | ||
| 1125 | + if (object.hasKey("/Extensions") && | ||
| 1126 | + object.getKey("/Extensions").isDictionary()) | ||
| 1127 | + { | ||
| 1128 | + extensions = object.getKey("/Extensions"); | ||
| 1129 | + } | ||
| 1130 | + } | ||
| 1131 | + else if (flags & f_in_extensions) | ||
| 1132 | + { | ||
| 1133 | + extensions = object; | ||
| 1134 | + } | ||
| 1135 | + if (extensions.isInitialized()) | ||
| 1136 | + { | ||
| 1137 | + std::set<std::string> keys = extensions.getKeys(); | ||
| 1138 | + if (keys.count("/ADBE") > 0) | ||
| 1139 | + { | ||
| 1140 | + have_extensions_adbe = true; | ||
| 1141 | + keys.erase("/ADBE"); | ||
| 1142 | + } | ||
| 1143 | + if (keys.size() > 0) | ||
| 1144 | + { | ||
| 1145 | + have_extensions_other = true; | ||
| 1146 | + } | ||
| 1147 | + } | ||
| 1148 | + | ||
| 1149 | + bool need_extensions_adbe = (this->final_extension_level > 0); | ||
| 1150 | + | ||
| 1151 | + bool write_new_extensions = false; | ||
| 1152 | + bool write_new_adbe = false; | ||
| 1153 | + bool suppress_existing_extensions = false; | ||
| 1154 | + bool suppress_existing_adbe = false; | ||
| 1155 | + if (is_root) | ||
| 1156 | + { | ||
| 1157 | + if (need_extensions_adbe) | ||
| 1158 | + { | ||
| 1159 | + if (! (have_extensions_other || have_extensions_adbe)) | ||
| 1160 | + { | ||
| 1161 | + // We need Extensions and don't have it. Create | ||
| 1162 | + // it here. | ||
| 1163 | + QTC::TC("qpdf", "QPDFWriter create Extensions", | ||
| 1164 | + this->qdf_mode ? 0 : 1); | ||
| 1165 | + write_new_extensions = true; | ||
| 1166 | + suppress_existing_extensions = true; | ||
| 1167 | + } | ||
| 1168 | + else | ||
| 1169 | + { | ||
| 1170 | + // Preserve existing Extensions and do the work | ||
| 1171 | + // in the extensions dictionary. | ||
| 1172 | + } | ||
| 1173 | + } | ||
| 1174 | + else if (! have_extensions_other) | ||
| 1175 | + { | ||
| 1176 | + // We have Extensions dictionary and don't want one. | ||
| 1177 | + suppress_existing_extensions = true; | ||
| 1178 | + if (have_extensions_adbe) | ||
| 1179 | + { | ||
| 1180 | + QTC::TC("qpdf", "QPDFWriter remove existing Extensions"); | ||
| 1181 | + } | ||
| 1182 | + } | ||
| 1183 | + } | ||
| 1184 | + else if (flags & f_in_extensions) | ||
| 1185 | + { | ||
| 1186 | + QTC::TC("qpdf", "QPDFWriter preserve Extensions"); | ||
| 1187 | + QPDFObjectHandle adbe = extensions.getKey("/ADBE"); | ||
| 1188 | + if (adbe.isDictionary() && | ||
| 1189 | + adbe.hasKey("/BaseVersion") && | ||
| 1190 | + adbe.getKey("/BaseVersion").isName() && | ||
| 1191 | + (adbe.getKey("/BaseVersion").getName() == | ||
| 1192 | + "/" + this->final_pdf_version) && | ||
| 1193 | + adbe.hasKey("/ExtensionLevel") && | ||
| 1194 | + adbe.getKey("/ExtensionLevel").isInteger() && | ||
| 1195 | + (adbe.getKey("/ExtensionLevel").getIntValue() == | ||
| 1196 | + this->final_extension_level)) | ||
| 1197 | + { | ||
| 1198 | + QTC::TC("qpdf", "QPDFWriter preserve ADBE"); | ||
| 1199 | + } | ||
| 1200 | + else | ||
| 1201 | + { | ||
| 1202 | + suppress_existing_adbe = true; | ||
| 1203 | + if (need_extensions_adbe) | ||
| 1204 | + { | ||
| 1205 | + write_new_adbe = true; | ||
| 1206 | + } | ||
| 1207 | + } | ||
| 1208 | + } | ||
| 1209 | + | ||
| 1040 | writeString("<<"); | 1210 | writeString("<<"); |
| 1041 | writeStringQDF("\n"); | 1211 | writeStringQDF("\n"); |
| 1212 | + | ||
| 1213 | + if (write_new_extensions || write_new_adbe) | ||
| 1214 | + { | ||
| 1215 | + writeStringQDF(indent); | ||
| 1216 | + writeStringQDF(" "); | ||
| 1217 | + writeStringNoQDF(" "); | ||
| 1218 | + if (write_new_extensions) | ||
| 1219 | + { | ||
| 1220 | + writeString("/Extensions << "); | ||
| 1221 | + } | ||
| 1222 | + writeString("/ADBE << /BaseVersion /"); | ||
| 1223 | + writeString(this->final_pdf_version); | ||
| 1224 | + writeString(" /ExtensionLevel "); | ||
| 1225 | + writeString(QUtil::int_to_string(this->final_extension_level)); | ||
| 1226 | + writeString(" >>"); | ||
| 1227 | + if (write_new_extensions) | ||
| 1228 | + { | ||
| 1229 | + writeString(" >>"); | ||
| 1230 | + } | ||
| 1231 | + writeStringQDF("\n"); | ||
| 1232 | + } | ||
| 1233 | + | ||
| 1042 | std::set<std::string> keys = object.getKeys(); | 1234 | std::set<std::string> keys = object.getKeys(); |
| 1043 | for (std::set<std::string>::iterator iter = keys.begin(); | 1235 | for (std::set<std::string>::iterator iter = keys.begin(); |
| 1044 | iter != keys.end(); ++iter) | 1236 | iter != keys.end(); ++iter) |
| @@ -1057,12 +1249,27 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | @@ -1057,12 +1249,27 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | ||
| 1057 | { | 1249 | { |
| 1058 | continue; | 1250 | continue; |
| 1059 | } | 1251 | } |
| 1252 | + | ||
| 1253 | + bool is_extensions = (is_root && (key == "/Extensions")); | ||
| 1254 | + if (suppress_existing_extensions && is_extensions) | ||
| 1255 | + { | ||
| 1256 | + QTC::TC("qpdf", "QPDFWriter skip Extensions"); | ||
| 1257 | + continue; | ||
| 1258 | + } | ||
| 1259 | + if (suppress_existing_adbe && (key == "/ADBE")) | ||
| 1260 | + { | ||
| 1261 | + QTC::TC("qpdf", "QPDFWriter skip ADBE"); | ||
| 1262 | + continue; | ||
| 1263 | + } | ||
| 1264 | + | ||
| 1265 | + | ||
| 1060 | writeStringQDF(indent); | 1266 | writeStringQDF(indent); |
| 1061 | writeStringQDF(" "); | 1267 | writeStringQDF(" "); |
| 1062 | writeStringNoQDF(" "); | 1268 | writeStringNoQDF(" "); |
| 1063 | writeString(QPDF_Name::normalizeName(key)); | 1269 | writeString(QPDF_Name::normalizeName(key)); |
| 1064 | writeString(" "); | 1270 | writeString(" "); |
| 1065 | - unparseChild(object.getKey(key), level + 1, child_flags); | 1271 | + unparseChild(object.getKey(key), level + 1, |
| 1272 | + child_flags | (is_extensions ? f_in_extensions : 0)); | ||
| 1066 | writeStringQDF("\n"); | 1273 | writeStringQDF("\n"); |
| 1067 | } | 1274 | } |
| 1068 | 1275 | ||
| @@ -1706,12 +1913,17 @@ QPDFWriter::prepareFileForWrite() | @@ -1706,12 +1913,17 @@ QPDFWriter::prepareFileForWrite() | ||
| 1706 | else if (node.isDictionary() || node.isStream()) | 1913 | else if (node.isDictionary() || node.isStream()) |
| 1707 | { | 1914 | { |
| 1708 | bool is_stream = false; | 1915 | bool is_stream = false; |
| 1916 | + bool is_root = false; | ||
| 1709 | QPDFObjectHandle dict = node; | 1917 | QPDFObjectHandle dict = node; |
| 1710 | if (node.isStream()) | 1918 | if (node.isStream()) |
| 1711 | { | 1919 | { |
| 1712 | is_stream = true; | 1920 | is_stream = true; |
| 1713 | dict = node.getDict(); | 1921 | dict = node.getDict(); |
| 1714 | } | 1922 | } |
| 1923 | + else if (pdf.getRoot().getObjectID() == node.getObjectID()) | ||
| 1924 | + { | ||
| 1925 | + is_root = true; | ||
| 1926 | + } | ||
| 1715 | 1927 | ||
| 1716 | std::set<std::string> keys = dict.getKeys(); | 1928 | std::set<std::string> keys = dict.getKeys(); |
| 1717 | for (std::set<std::string>::iterator iter = keys.begin(); | 1929 | for (std::set<std::string>::iterator iter = keys.begin(); |
| @@ -1720,19 +1932,43 @@ QPDFWriter::prepareFileForWrite() | @@ -1720,19 +1932,43 @@ QPDFWriter::prepareFileForWrite() | ||
| 1720 | std::string const& key = *iter; | 1932 | std::string const& key = *iter; |
| 1721 | QPDFObjectHandle oh = dict.getKey(key); | 1933 | QPDFObjectHandle oh = dict.getKey(key); |
| 1722 | bool add_to_queue = true; | 1934 | bool add_to_queue = true; |
| 1723 | - if (oh.isIndirect()) | 1935 | + if (is_stream) |
| 1936 | + { | ||
| 1937 | + if (oh.isIndirect() && | ||
| 1938 | + ((key == "/Length") || | ||
| 1939 | + (key == "/Filter") || | ||
| 1940 | + (key == "/DecodeParms"))) | ||
| 1941 | + { | ||
| 1942 | + QTC::TC("qpdf", "QPDFWriter make stream key direct"); | ||
| 1943 | + add_to_queue = false; | ||
| 1944 | + oh.makeDirect(); | ||
| 1945 | + dict.replaceKey(key, oh); | ||
| 1946 | + } | ||
| 1947 | + } | ||
| 1948 | + else if (is_root) | ||
| 1724 | { | 1949 | { |
| 1725 | - if (is_stream) | 1950 | + if ((key == "/Extensions") && (oh.isDictionary())) |
| 1726 | { | 1951 | { |
| 1727 | - if ((key == "/Length") || | ||
| 1728 | - (key == "/Filter") || | ||
| 1729 | - (key == "/DecodeParms")) | 1952 | + bool extensions_indirect = false; |
| 1953 | + if (oh.isIndirect()) | ||
| 1730 | { | 1954 | { |
| 1731 | - QTC::TC("qpdf", "QPDF make stream key direct"); | 1955 | + QTC::TC("qpdf", "QPDFWriter make Extensions direct"); |
| 1956 | + extensions_indirect = true; | ||
| 1732 | add_to_queue = false; | 1957 | add_to_queue = false; |
| 1733 | - oh.makeDirect(); | 1958 | + oh = oh.shallowCopy(); |
| 1734 | dict.replaceKey(key, oh); | 1959 | dict.replaceKey(key, oh); |
| 1735 | } | 1960 | } |
| 1961 | + if (oh.hasKey("/ADBE")) | ||
| 1962 | + { | ||
| 1963 | + QPDFObjectHandle adbe = oh.getKey("/ADBE"); | ||
| 1964 | + if (adbe.isIndirect()) | ||
| 1965 | + { | ||
| 1966 | + QTC::TC("qpdf", "QPDFWriter make ADBE direct", | ||
| 1967 | + extensions_indirect ? 0 : 1); | ||
| 1968 | + adbe.makeDirect(); | ||
| 1969 | + oh.replaceKey("/ADBE", adbe); | ||
| 1970 | + } | ||
| 1971 | + } | ||
| 1736 | } | 1972 | } |
| 1737 | } | 1973 | } |
| 1738 | 1974 | ||
| @@ -1791,7 +2027,8 @@ QPDFWriter::write() | @@ -1791,7 +2027,8 @@ QPDFWriter::write() | ||
| 1791 | int major = 0; | 2027 | int major = 0; |
| 1792 | int minor = 0; | 2028 | int minor = 0; |
| 1793 | parseVersion(this->forced_pdf_version, major, minor); | 2029 | parseVersion(this->forced_pdf_version, major, minor); |
| 1794 | - disableIncompatibleEncryption(major, minor); | 2030 | + disableIncompatibleEncryption(major, minor, |
| 2031 | + this->forced_extension_level); | ||
| 1795 | if (compareVersions(major, minor, 1, 5) < 0) | 2032 | if (compareVersions(major, minor, 1, 5) < 0) |
| 1796 | { | 2033 | { |
| 1797 | QTC::TC("qpdf", "QPDFWriter forcing object stream disable"); | 2034 | QTC::TC("qpdf", "QPDFWriter forcing object stream disable"); |
| @@ -1938,16 +2175,18 @@ QPDFWriter::writeEncryptionDictionary() | @@ -1938,16 +2175,18 @@ QPDFWriter::writeEncryptionDictionary() | ||
| 1938 | void | 2175 | void |
| 1939 | QPDFWriter::writeHeader() | 2176 | QPDFWriter::writeHeader() |
| 1940 | { | 2177 | { |
| 1941 | - setMinimumPDFVersion(pdf.getPDFVersion()); | ||
| 1942 | - std::string version = this->min_pdf_version; | 2178 | + setMinimumPDFVersion(pdf.getPDFVersion(), pdf.getExtensionLevel()); |
| 2179 | + this->final_pdf_version = this->min_pdf_version; | ||
| 2180 | + this->final_extension_level = this->min_extension_level; | ||
| 1943 | if (! this->forced_pdf_version.empty()) | 2181 | if (! this->forced_pdf_version.empty()) |
| 1944 | { | 2182 | { |
| 1945 | QTC::TC("qpdf", "QPDFWriter using forced PDF version"); | 2183 | QTC::TC("qpdf", "QPDFWriter using forced PDF version"); |
| 1946 | - version = this->forced_pdf_version; | 2184 | + this->final_pdf_version = this->forced_pdf_version; |
| 2185 | + this->final_extension_level = this->forced_extension_level; | ||
| 1947 | } | 2186 | } |
| 1948 | 2187 | ||
| 1949 | writeString("%PDF-"); | 2188 | writeString("%PDF-"); |
| 1950 | - writeString(version); | 2189 | + writeString(this->final_pdf_version); |
| 1951 | // This string of binary characters would not be valid UTF-8, so | 2190 | // This string of binary characters would not be valid UTF-8, so |
| 1952 | // it really should be treated as binary. | 2191 | // it really should be treated as binary. |
| 1953 | writeString("\n%\xbf\xf7\xa2\xfe\n"); | 2192 | writeString("\n%\xbf\xf7\xa2\xfe\n"); |
qpdf/qpdf.cc
| @@ -189,6 +189,9 @@ familiar with the PDF file format or who are PDF developers.\n\ | @@ -189,6 +189,9 @@ familiar with the PDF file format or who are PDF developers.\n\ | ||
| 189 | --min-version=version sets the minimum PDF version of the output file\n\ | 189 | --min-version=version sets the minimum PDF version of the output file\n\ |
| 190 | --force-version=version forces this to be the PDF version of the output file\n\ | 190 | --force-version=version forces this to be the PDF version of the output file\n\ |
| 191 | \n\ | 191 | \n\ |
| 192 | +Version numbers may be expressed as major.minor.extension-level, so 1.7.3\n\ | ||
| 193 | +means PDF version 1.7 at extension level 3.\n\ | ||
| 194 | +\n\ | ||
| 192 | Values for stream data options:\n\ | 195 | Values for stream data options:\n\ |
| 193 | \n\ | 196 | \n\ |
| 194 | compress recompress stream data when possible (default)\n\ | 197 | compress recompress stream data when possible (default)\n\ |
| @@ -838,6 +841,21 @@ QPDFPageData::QPDFPageData(QPDF* qpdf, char const* range) : | @@ -838,6 +841,21 @@ QPDFPageData::QPDFPageData(QPDF* qpdf, char const* range) : | ||
| 838 | this->selected_pages = parse_numrange(range, (int)this->orig_pages.size()); | 841 | this->selected_pages = parse_numrange(range, (int)this->orig_pages.size()); |
| 839 | } | 842 | } |
| 840 | 843 | ||
| 844 | +static void parse_version(std::string const& full_version_string, | ||
| 845 | + std::string& version, int& extension_level) | ||
| 846 | +{ | ||
| 847 | + PointerHolder<char> vp(true, QUtil::copy_string(full_version_string)); | ||
| 848 | + char* v = vp.getPointer(); | ||
| 849 | + char* p1 = strchr(v, '.'); | ||
| 850 | + char* p2 = (p1 ? strchr(1 + p1, '.') : 0); | ||
| 851 | + if (p2 && *(p2 + 1)) | ||
| 852 | + { | ||
| 853 | + *p2++ = '\0'; | ||
| 854 | + extension_level = atoi(p2); | ||
| 855 | + } | ||
| 856 | + version = v; | ||
| 857 | +} | ||
| 858 | + | ||
| 841 | int main(int argc, char* argv[]) | 859 | int main(int argc, char* argv[]) |
| 842 | { | 860 | { |
| 843 | whoami = QUtil::getWhoami(argv[0]); | 861 | whoami = QUtil::getWhoami(argv[0]); |
| @@ -1370,8 +1388,14 @@ int main(int argc, char* argv[]) | @@ -1370,8 +1388,14 @@ int main(int argc, char* argv[]) | ||
| 1370 | std::cout << "checking " << infilename << std::endl; | 1388 | std::cout << "checking " << infilename << std::endl; |
| 1371 | try | 1389 | try |
| 1372 | { | 1390 | { |
| 1373 | - std::cout << "PDF Version: " << pdf.getPDFVersion() | ||
| 1374 | - << std::endl; | 1391 | + int extension_level = pdf.getExtensionLevel(); |
| 1392 | + std::cout << "PDF Version: " << pdf.getPDFVersion(); | ||
| 1393 | + if (extension_level > 0) | ||
| 1394 | + { | ||
| 1395 | + std::cout << " extension level " | ||
| 1396 | + << pdf.getExtensionLevel(); | ||
| 1397 | + } | ||
| 1398 | + std::cout << std::endl; | ||
| 1375 | ::show_encryption(pdf); | 1399 | ::show_encryption(pdf); |
| 1376 | if (pdf.isLinearized()) | 1400 | if (pdf.isLinearized()) |
| 1377 | { | 1401 | { |
| @@ -1603,11 +1627,17 @@ int main(int argc, char* argv[]) | @@ -1603,11 +1627,17 @@ int main(int argc, char* argv[]) | ||
| 1603 | } | 1627 | } |
| 1604 | if (! min_version.empty()) | 1628 | if (! min_version.empty()) |
| 1605 | { | 1629 | { |
| 1606 | - w.setMinimumPDFVersion(min_version); | 1630 | + std::string version; |
| 1631 | + int extension_level = 0; | ||
| 1632 | + parse_version(min_version, version, extension_level); | ||
| 1633 | + w.setMinimumPDFVersion(version, extension_level); | ||
| 1607 | } | 1634 | } |
| 1608 | if (! force_version.empty()) | 1635 | if (! force_version.empty()) |
| 1609 | { | 1636 | { |
| 1610 | - w.forcePDFVersion(force_version); | 1637 | + std::string version; |
| 1638 | + int extension_level = 0; | ||
| 1639 | + parse_version(force_version, version, extension_level); | ||
| 1640 | + w.forcePDFVersion(version, extension_level); | ||
| 1611 | } | 1641 | } |
| 1612 | w.write(); | 1642 | w.write(); |
| 1613 | } | 1643 | } |
qpdf/qpdf.testcov
| @@ -151,7 +151,7 @@ qpdf-c called qpdf_allow_modify_form 0 | @@ -151,7 +151,7 @@ qpdf-c called qpdf_allow_modify_form 0 | ||
| 151 | qpdf-c called qpdf_allow_modify_annotation 0 | 151 | qpdf-c called qpdf_allow_modify_annotation 0 |
| 152 | qpdf-c called qpdf_allow_modify_other 0 | 152 | qpdf-c called qpdf_allow_modify_other 0 |
| 153 | qpdf-c called qpdf_allow_modify_all 0 | 153 | qpdf-c called qpdf_allow_modify_all 0 |
| 154 | -QPDFWriter increasing minimum version 0 | 154 | +QPDFWriter increasing minimum version 1 |
| 155 | QPDFWriter using forced PDF version 0 | 155 | QPDFWriter using forced PDF version 0 |
| 156 | qpdf-c called qpdf_set_minimum_pdf_version 0 | 156 | qpdf-c called qpdf_set_minimum_pdf_version 0 |
| 157 | qpdf-c called qpdf_force_pdf_version 0 | 157 | qpdf-c called qpdf_force_pdf_version 0 |
| @@ -243,4 +243,13 @@ QPDFWriter extra header text no newline 0 | @@ -243,4 +243,13 @@ QPDFWriter extra header text no newline 0 | ||
| 243 | QPDFWriter extra header text add newline 0 | 243 | QPDFWriter extra header text add newline 0 |
| 244 | QPDF bogus 0 offset 0 | 244 | QPDF bogus 0 offset 0 |
| 245 | QPDF global offset 0 | 245 | QPDF global offset 0 |
| 246 | -QPDF make stream key direct 0 | 246 | +QPDFWriter make stream key direct 0 |
| 247 | +QPDFWriter increasing extension level 0 | ||
| 248 | +QPDFWriter make Extensions direct 0 | ||
| 249 | +QPDFWriter make ADBE direct 1 | ||
| 250 | +QPDFWriter preserve Extensions 0 | ||
| 251 | +QPDFWriter create Extensions 1 | ||
| 252 | +QPDFWriter skip ADBE 0 | ||
| 253 | +QPDFWriter remove existing Extensions 0 | ||
| 254 | +QPDFWriter skip Extensions 0 | ||
| 255 | +QPDFWriter preserve ADBE 0 |
qpdf/qtest/qpdf.test
| @@ -111,6 +111,55 @@ $td->runtest("new stream", | @@ -111,6 +111,55 @@ $td->runtest("new stream", | ||
| 111 | 111 | ||
| 112 | show_ntests(); | 112 | show_ntests(); |
| 113 | # ---------- | 113 | # ---------- |
| 114 | +$td->notify("--- Extensions Dictionary Tests ---"); | ||
| 115 | +my @ext_inputs = ('minimal.pdf', 'extensions-adbe.pdf', | ||
| 116 | + 'extensions-other.pdf', 'extensions-adbe-other.pdf'); | ||
| 117 | +my @new_versions = ('1.3', '1.6', '1.7.1', '1.7.2', '1.7.3', | ||
| 118 | + '1.8', '1.8.0', '1.8.2', '1.8.5'); | ||
| 119 | +$n_tests += (4 * @new_versions + 3) * @ext_inputs; | ||
| 120 | +foreach my $input (@ext_inputs) | ||
| 121 | +{ | ||
| 122 | + my $base = $input; | ||
| 123 | + $base =~ s/\.pdf$//; | ||
| 124 | + if ($base eq 'minimal') | ||
| 125 | + { | ||
| 126 | + $base = 'extensions-none'; | ||
| 127 | + } | ||
| 128 | + foreach my $version (@new_versions) | ||
| 129 | + { | ||
| 130 | + foreach my $op (qw(min force)) | ||
| 131 | + { | ||
| 132 | + $td->runtest("$input: $op version to $version", | ||
| 133 | + {$td->COMMAND => | ||
| 134 | + "qpdf --static-id" . | ||
| 135 | + " --$op-version=$version $input a.pdf"}, | ||
| 136 | + {$td->STRING => "", $td->EXIT_STATUS => 0}); | ||
| 137 | + $td->runtest("check version information", | ||
| 138 | + {$td->COMMAND => "test_driver 34 a.pdf"}, | ||
| 139 | + {$td->FILE => "$base-$op-$version.out", | ||
| 140 | + $td->EXIT_STATUS => 0}, | ||
| 141 | + $td->NORMALIZE_NEWLINES); | ||
| 142 | + if (($op eq 'force') && ($version eq '1.8.5')) | ||
| 143 | + { | ||
| 144 | + # Look at the actual file for a few cases to make sure | ||
| 145 | + # qdf and non-qdf output are okay | ||
| 146 | + $td->runtest("check file", | ||
| 147 | + {$td->FILE => "a.pdf"}, | ||
| 148 | + {$td->FILE => "$base-$op-$version.pdf"}); | ||
| 149 | + $td->runtest("$input: $op version to $version", | ||
| 150 | + {$td->COMMAND => | ||
| 151 | + "qpdf --qdf --static-id" . | ||
| 152 | + " --$op-version=$version $input a.qdf"}, | ||
| 153 | + {$td->STRING => "", $td->EXIT_STATUS => 0}); | ||
| 154 | + $td->runtest("check file", | ||
| 155 | + {$td->FILE => "a.qdf"}, | ||
| 156 | + {$td->FILE => "$base-$op-$version.qdf"}); | ||
| 157 | + } | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | +} | ||
| 161 | +show_ntests(); | ||
| 162 | +# ---------- | ||
| 114 | $td->notify("--- Page API Tests ---"); | 163 | $td->notify("--- Page API Tests ---"); |
| 115 | $n_tests += 9; | 164 | $n_tests += 9; |
| 116 | 165 | ||
| @@ -147,6 +196,7 @@ $td->runtest("remove page we don't have", | @@ -147,6 +196,7 @@ $td->runtest("remove page we don't have", | ||
| 147 | {$td->COMMAND => "test_driver 22 page_api_1.pdf"}, | 196 | {$td->COMMAND => "test_driver 22 page_api_1.pdf"}, |
| 148 | {$td->FILE => "page_api_1.out2", $td->EXIT_STATUS => 2}, | 197 | {$td->FILE => "page_api_1.out2", $td->EXIT_STATUS => 2}, |
| 149 | $td->NORMALIZE_NEWLINES); | 198 | $td->NORMALIZE_NEWLINES); |
| 199 | +show_ntests(); | ||
| 150 | # ---------- | 200 | # ---------- |
| 151 | $td->notify("--- Miscellaneous Tests ---"); | 201 | $td->notify("--- Miscellaneous Tests ---"); |
| 152 | $n_tests += 57; | 202 | $n_tests += 57; |
| @@ -466,6 +516,7 @@ foreach my $d (@nrange_tests) | @@ -466,6 +516,7 @@ foreach my $d (@nrange_tests) | ||
| 466 | $td->NORMALIZE_NEWLINES); | 516 | $td->NORMALIZE_NEWLINES); |
| 467 | } | 517 | } |
| 468 | 518 | ||
| 519 | +show_ntests(); | ||
| 469 | # ---------- | 520 | # ---------- |
| 470 | $td->notify("--- Merging and Splitting ---"); | 521 | $td->notify("--- Merging and Splitting ---"); |
| 471 | $n_tests += 6; | 522 | $n_tests += 6; |
| @@ -513,6 +564,7 @@ $td->runtest("avoid respecification of password", | @@ -513,6 +564,7 @@ $td->runtest("avoid respecification of password", | ||
| 513 | $td->runtest("check output", | 564 | $td->runtest("check output", |
| 514 | {$td->FILE => "a.pdf"}, | 565 | {$td->FILE => "a.pdf"}, |
| 515 | {$td->FILE => "pages-copy-encryption.pdf"}); | 566 | {$td->FILE => "pages-copy-encryption.pdf"}); |
| 567 | +show_ntests(); | ||
| 516 | # ---------- | 568 | # ---------- |
| 517 | $td->notify("--- PDF From Scratch ---"); | 569 | $td->notify("--- PDF From Scratch ---"); |
| 518 | $n_tests += 2; | 570 | $n_tests += 2; |
| @@ -524,6 +576,7 @@ $td->runtest("basic qpdf from scratch", | @@ -524,6 +576,7 @@ $td->runtest("basic qpdf from scratch", | ||
| 524 | $td->runtest("check output", | 576 | $td->runtest("check output", |
| 525 | {$td->FILE => "a.pdf"}, | 577 | {$td->FILE => "a.pdf"}, |
| 526 | {$td->FILE => "from-scratch-0.pdf"}); | 578 | {$td->FILE => "from-scratch-0.pdf"}); |
| 579 | +show_ntests(); | ||
| 527 | # ---------- | 580 | # ---------- |
| 528 | $td->notify("--- Copy Foreign Objects ---"); | 581 | $td->notify("--- Copy Foreign Objects ---"); |
| 529 | $n_tests += 7; | 582 | $n_tests += 7; |
| @@ -546,6 +599,7 @@ $td->runtest("copy objects error", | @@ -546,6 +599,7 @@ $td->runtest("copy objects error", | ||
| 546 | {$td->FILE => "copy-foreign-objects-errors.out", | 599 | {$td->FILE => "copy-foreign-objects-errors.out", |
| 547 | $td->EXIT_STATUS => 0}, | 600 | $td->EXIT_STATUS => 0}, |
| 548 | $td->NORMALIZE_NEWLINES); | 601 | $td->NORMALIZE_NEWLINES); |
| 602 | +show_ntests(); | ||
| 549 | # ---------- | 603 | # ---------- |
| 550 | $td->notify("--- Error Condition Tests ---"); | 604 | $td->notify("--- Error Condition Tests ---"); |
| 551 | # $n_tests incremented after initialization of badfiles below. | 605 | # $n_tests incremented after initialization of badfiles below. |
qpdf/qtest/qpdf/extensions-adbe-force-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-force-1.8.5.pdf
0 โ 100644
No preview for this file type
qpdf/qtest/qpdf/extensions-adbe-force-1.8.5.qdf
0 โ 100644
| 1 | +%PDF-1.8 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +%% Original object ID: 1 0 | ||
| 6 | +1 0 obj | ||
| 7 | +<< | ||
| 8 | + /Extensions << | ||
| 9 | + /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> | ||
| 10 | + >> | ||
| 11 | + /Pages 2 0 R | ||
| 12 | + /Type /Catalog | ||
| 13 | +>> | ||
| 14 | +endobj | ||
| 15 | + | ||
| 16 | +%% Original object ID: 2 0 | ||
| 17 | +2 0 obj | ||
| 18 | +<< | ||
| 19 | + /Count 1 | ||
| 20 | + /Kids [ | ||
| 21 | + 3 0 R | ||
| 22 | + ] | ||
| 23 | + /Type /Pages | ||
| 24 | +>> | ||
| 25 | +endobj | ||
| 26 | + | ||
| 27 | +%% Page 1 | ||
| 28 | +%% Original object ID: 3 0 | ||
| 29 | +3 0 obj | ||
| 30 | +<< | ||
| 31 | + /Contents 4 0 R | ||
| 32 | + /MediaBox [ | ||
| 33 | + 0 | ||
| 34 | + 0 | ||
| 35 | + 612 | ||
| 36 | + 792 | ||
| 37 | + ] | ||
| 38 | + /Parent 2 0 R | ||
| 39 | + /Resources << | ||
| 40 | + /Font << | ||
| 41 | + /F1 6 0 R | ||
| 42 | + >> | ||
| 43 | + /ProcSet 7 0 R | ||
| 44 | + >> | ||
| 45 | + /Type /Page | ||
| 46 | +>> | ||
| 47 | +endobj | ||
| 48 | + | ||
| 49 | +%% Contents for page 1 | ||
| 50 | +%% Original object ID: 4 0 | ||
| 51 | +4 0 obj | ||
| 52 | +<< | ||
| 53 | + /Length 5 0 R | ||
| 54 | +>> | ||
| 55 | +stream | ||
| 56 | +BT | ||
| 57 | + /F1 24 Tf | ||
| 58 | + 72 720 Td | ||
| 59 | + (Potato) Tj | ||
| 60 | +ET | ||
| 61 | +endstream | ||
| 62 | +endobj | ||
| 63 | + | ||
| 64 | +5 0 obj | ||
| 65 | +44 | ||
| 66 | +endobj | ||
| 67 | + | ||
| 68 | +%% Original object ID: 6 0 | ||
| 69 | +6 0 obj | ||
| 70 | +<< | ||
| 71 | + /BaseFont /Helvetica | ||
| 72 | + /Encoding /WinAnsiEncoding | ||
| 73 | + /Name /F1 | ||
| 74 | + /Subtype /Type1 | ||
| 75 | + /Type /Font | ||
| 76 | +>> | ||
| 77 | +endobj | ||
| 78 | + | ||
| 79 | +%% Original object ID: 7 0 | ||
| 80 | +7 0 obj | ||
| 81 | +[ | ||
| 82 | |||
| 83 | + /Text | ||
| 84 | +] | ||
| 85 | +endobj | ||
| 86 | + | ||
| 87 | +xref | ||
| 88 | +0 8 | ||
| 89 | +0000000000 65535 f | ||
| 90 | +0000000052 00000 n | ||
| 91 | +0000000207 00000 n | ||
| 92 | +0000000316 00000 n | ||
| 93 | +0000000558 00000 n | ||
| 94 | +0000000657 00000 n | ||
| 95 | +0000000703 00000 n | ||
| 96 | +0000000848 00000 n | ||
| 97 | +trailer << | ||
| 98 | + /Root 1 0 R | ||
| 99 | + /Size 8 | ||
| 100 | + /ID [<e42c124696c09bd2cacaf7196e9c88a0><31415926535897932384626433832795>] | ||
| 101 | +>> | ||
| 102 | +startxref | ||
| 103 | +883 | ||
| 104 | +%%EOF |
qpdf/qtest/qpdf/extensions-adbe-force-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-min-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.5.pdf
0 โ 100644
No preview for this file type
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.5.qdf
0 โ 100644
| 1 | +%PDF-1.8 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +%% Original object ID: 1 0 | ||
| 6 | +1 0 obj | ||
| 7 | +<< | ||
| 8 | + /Extensions << | ||
| 9 | + /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> | ||
| 10 | + /Potato << | ||
| 11 | + /BaseVersion /3.14159 | ||
| 12 | + /ExtensionLevel 16059 | ||
| 13 | + >> | ||
| 14 | + >> | ||
| 15 | + /Pages 2 0 R | ||
| 16 | + /Type /Catalog | ||
| 17 | +>> | ||
| 18 | +endobj | ||
| 19 | + | ||
| 20 | +%% Original object ID: 2 0 | ||
| 21 | +2 0 obj | ||
| 22 | +<< | ||
| 23 | + /Count 1 | ||
| 24 | + /Kids [ | ||
| 25 | + 3 0 R | ||
| 26 | + ] | ||
| 27 | + /Type /Pages | ||
| 28 | +>> | ||
| 29 | +endobj | ||
| 30 | + | ||
| 31 | +%% Page 1 | ||
| 32 | +%% Original object ID: 3 0 | ||
| 33 | +3 0 obj | ||
| 34 | +<< | ||
| 35 | + /Contents 4 0 R | ||
| 36 | + /MediaBox [ | ||
| 37 | + 0 | ||
| 38 | + 0 | ||
| 39 | + 612 | ||
| 40 | + 792 | ||
| 41 | + ] | ||
| 42 | + /Parent 2 0 R | ||
| 43 | + /Resources << | ||
| 44 | + /Font << | ||
| 45 | + /F1 6 0 R | ||
| 46 | + >> | ||
| 47 | + /ProcSet 7 0 R | ||
| 48 | + >> | ||
| 49 | + /Type /Page | ||
| 50 | +>> | ||
| 51 | +endobj | ||
| 52 | + | ||
| 53 | +%% Contents for page 1 | ||
| 54 | +%% Original object ID: 4 0 | ||
| 55 | +4 0 obj | ||
| 56 | +<< | ||
| 57 | + /Length 5 0 R | ||
| 58 | +>> | ||
| 59 | +stream | ||
| 60 | +BT | ||
| 61 | + /F1 24 Tf | ||
| 62 | + 72 720 Td | ||
| 63 | + (Potato) Tj | ||
| 64 | +ET | ||
| 65 | +endstream | ||
| 66 | +endobj | ||
| 67 | + | ||
| 68 | +5 0 obj | ||
| 69 | +44 | ||
| 70 | +endobj | ||
| 71 | + | ||
| 72 | +%% Original object ID: 6 0 | ||
| 73 | +6 0 obj | ||
| 74 | +<< | ||
| 75 | + /BaseFont /Helvetica | ||
| 76 | + /Encoding /WinAnsiEncoding | ||
| 77 | + /Name /F1 | ||
| 78 | + /Subtype /Type1 | ||
| 79 | + /Type /Font | ||
| 80 | +>> | ||
| 81 | +endobj | ||
| 82 | + | ||
| 83 | +%% Original object ID: 7 0 | ||
| 84 | +7 0 obj | ||
| 85 | +[ | ||
| 86 | |||
| 87 | + /Text | ||
| 88 | +] | ||
| 89 | +endobj | ||
| 90 | + | ||
| 91 | +xref | ||
| 92 | +0 8 | ||
| 93 | +0000000000 65535 f | ||
| 94 | +0000000052 00000 n | ||
| 95 | +0000000285 00000 n | ||
| 96 | +0000000394 00000 n | ||
| 97 | +0000000636 00000 n | ||
| 98 | +0000000735 00000 n | ||
| 99 | +0000000781 00000 n | ||
| 100 | +0000000926 00000 n | ||
| 101 | +trailer << | ||
| 102 | + /Root 1 0 R | ||
| 103 | + /Size 8 | ||
| 104 | + /ID [<484577389048fa45fc00a1f5b434efa5><31415926535897932384626433832795>] | ||
| 105 | +>> | ||
| 106 | +startxref | ||
| 107 | +961 | ||
| 108 | +%%EOF |
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-adbe-other.pdf
0 โ 100644
| 1 | +%PDF-1.7 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +1 0 obj | ||
| 6 | +<< | ||
| 7 | + /Pages 2 0 R | ||
| 8 | + /Type /Catalog | ||
| 9 | + /Extensions << | ||
| 10 | + /ADBE 8 0 R | ||
| 11 | + /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> | ||
| 12 | + >> | ||
| 13 | +>> | ||
| 14 | +endobj | ||
| 15 | + | ||
| 16 | +2 0 obj | ||
| 17 | +<< | ||
| 18 | + /Count 1 | ||
| 19 | + /Kids [ | ||
| 20 | + 3 0 R | ||
| 21 | + ] | ||
| 22 | + /Type /Pages | ||
| 23 | +>> | ||
| 24 | +endobj | ||
| 25 | + | ||
| 26 | +%% Page 1 | ||
| 27 | +3 0 obj | ||
| 28 | +<< | ||
| 29 | + /Contents 4 0 R | ||
| 30 | + /MediaBox [ | ||
| 31 | + 0 | ||
| 32 | + 0 | ||
| 33 | + 612 | ||
| 34 | + 792 | ||
| 35 | + ] | ||
| 36 | + /Parent 2 0 R | ||
| 37 | + /Resources << | ||
| 38 | + /Font << | ||
| 39 | + /F1 6 0 R | ||
| 40 | + >> | ||
| 41 | + /ProcSet 7 0 R | ||
| 42 | + >> | ||
| 43 | + /Type /Page | ||
| 44 | +>> | ||
| 45 | +endobj | ||
| 46 | + | ||
| 47 | +%% Contents for page 1 | ||
| 48 | +4 0 obj | ||
| 49 | +<< | ||
| 50 | + /Length 5 0 R | ||
| 51 | +>> | ||
| 52 | +stream | ||
| 53 | +BT | ||
| 54 | + /F1 24 Tf | ||
| 55 | + 72 720 Td | ||
| 56 | + (Potato) Tj | ||
| 57 | +ET | ||
| 58 | +endstream | ||
| 59 | +endobj | ||
| 60 | + | ||
| 61 | +5 0 obj | ||
| 62 | +44 | ||
| 63 | +endobj | ||
| 64 | + | ||
| 65 | +6 0 obj | ||
| 66 | +<< | ||
| 67 | + /BaseFont /Helvetica | ||
| 68 | + /Encoding /WinAnsiEncoding | ||
| 69 | + /Name /F1 | ||
| 70 | + /Subtype /Type1 | ||
| 71 | + /Type /Font | ||
| 72 | +>> | ||
| 73 | +endobj | ||
| 74 | + | ||
| 75 | +7 0 obj | ||
| 76 | +[ | ||
| 77 | |||
| 78 | + /Text | ||
| 79 | +] | ||
| 80 | +endobj | ||
| 81 | + | ||
| 82 | +8 0 obj | ||
| 83 | +<< /BaseVersion /1.7 /ExtensionLevel 2 >> | ||
| 84 | +endobj | ||
| 85 | + | ||
| 86 | +xref | ||
| 87 | +0 9 | ||
| 88 | +0000000000 65535 f | ||
| 89 | +0000000025 00000 n | ||
| 90 | +0000000179 00000 n | ||
| 91 | +0000000261 00000 n | ||
| 92 | +0000000476 00000 n | ||
| 93 | +0000000575 00000 n | ||
| 94 | +0000000594 00000 n | ||
| 95 | +0000000712 00000 n | ||
| 96 | +0000000747 00000 n | ||
| 97 | +trailer << | ||
| 98 | + /Root 1 0 R | ||
| 99 | + /Size 9 | ||
| 100 | + /ID [<484577389048fa45fc00a1f5b434efa5><484577389048fa45fc00a1f5b434efa5>] | ||
| 101 | +>> | ||
| 102 | +startxref | ||
| 103 | +805 | ||
| 104 | +%%EOF |
qpdf/qtest/qpdf/extensions-adbe.pdf
0 โ 100644
| 1 | +%PDF-1.7 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +1 0 obj | ||
| 6 | +<< | ||
| 7 | + /Pages 2 0 R | ||
| 8 | + /Type /Catalog | ||
| 9 | + /Extensions 8 0 R | ||
| 10 | +>> | ||
| 11 | +endobj | ||
| 12 | + | ||
| 13 | +2 0 obj | ||
| 14 | +<< | ||
| 15 | + /Count 1 | ||
| 16 | + /Kids [ | ||
| 17 | + 3 0 R | ||
| 18 | + ] | ||
| 19 | + /Type /Pages | ||
| 20 | +>> | ||
| 21 | +endobj | ||
| 22 | + | ||
| 23 | +%% Page 1 | ||
| 24 | +3 0 obj | ||
| 25 | +<< | ||
| 26 | + /Contents 4 0 R | ||
| 27 | + /MediaBox [ | ||
| 28 | + 0 | ||
| 29 | + 0 | ||
| 30 | + 612 | ||
| 31 | + 792 | ||
| 32 | + ] | ||
| 33 | + /Parent 2 0 R | ||
| 34 | + /Resources << | ||
| 35 | + /Font << | ||
| 36 | + /F1 6 0 R | ||
| 37 | + >> | ||
| 38 | + /ProcSet 7 0 R | ||
| 39 | + >> | ||
| 40 | + /Type /Page | ||
| 41 | +>> | ||
| 42 | +endobj | ||
| 43 | + | ||
| 44 | +%% Contents for page 1 | ||
| 45 | +4 0 obj | ||
| 46 | +<< | ||
| 47 | + /Length 5 0 R | ||
| 48 | +>> | ||
| 49 | +stream | ||
| 50 | +BT | ||
| 51 | + /F1 24 Tf | ||
| 52 | + 72 720 Td | ||
| 53 | + (Potato) Tj | ||
| 54 | +ET | ||
| 55 | +endstream | ||
| 56 | +endobj | ||
| 57 | + | ||
| 58 | +5 0 obj | ||
| 59 | +44 | ||
| 60 | +endobj | ||
| 61 | + | ||
| 62 | +6 0 obj | ||
| 63 | +<< | ||
| 64 | + /BaseFont /Helvetica | ||
| 65 | + /Encoding /WinAnsiEncoding | ||
| 66 | + /Name /F1 | ||
| 67 | + /Subtype /Type1 | ||
| 68 | + /Type /Font | ||
| 69 | +>> | ||
| 70 | +endobj | ||
| 71 | + | ||
| 72 | +7 0 obj | ||
| 73 | +[ | ||
| 74 | |||
| 75 | + /Text | ||
| 76 | +] | ||
| 77 | +endobj | ||
| 78 | + | ||
| 79 | +8 0 obj | ||
| 80 | +<< /ADBE 9 0 R >> | ||
| 81 | +endobj | ||
| 82 | + | ||
| 83 | +9 0 obj | ||
| 84 | +<< /BaseVersion /1.7 /ExtensionLevel 2 /URL (http://something.adobe.com) >> | ||
| 85 | +endobj | ||
| 86 | + | ||
| 87 | +xref | ||
| 88 | +0 10 | ||
| 89 | +0000000000 65535 f | ||
| 90 | +0000000025 00000 n | ||
| 91 | +0000000099 00000 n | ||
| 92 | +0000000181 00000 n | ||
| 93 | +0000000396 00000 n | ||
| 94 | +0000000495 00000 n | ||
| 95 | +0000000514 00000 n | ||
| 96 | +0000000632 00000 n | ||
| 97 | +0000000667 00000 n | ||
| 98 | +0000000701 00000 n | ||
| 99 | +trailer << | ||
| 100 | + /Root 1 0 R | ||
| 101 | + /Size 10 | ||
| 102 | + /ID [<e42c124696c09bd2cacaf7196e9c88a0><e42c124696c09bd2cacaf7196e9c88a0>] | ||
| 103 | +>> | ||
| 104 | +startxref | ||
| 105 | +793 | ||
| 106 | +%%EOF |
qpdf/qtest/qpdf/extensions-none-force-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-force-1.8.5.pdf
0 โ 100644
No preview for this file type
qpdf/qtest/qpdf/extensions-none-force-1.8.5.qdf
0 โ 100644
| 1 | +%PDF-1.8 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +%% Original object ID: 1 0 | ||
| 6 | +1 0 obj | ||
| 7 | +<< | ||
| 8 | + /Extensions << /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> >> | ||
| 9 | + /Pages 2 0 R | ||
| 10 | + /Type /Catalog | ||
| 11 | +>> | ||
| 12 | +endobj | ||
| 13 | + | ||
| 14 | +%% Original object ID: 2 0 | ||
| 15 | +2 0 obj | ||
| 16 | +<< | ||
| 17 | + /Count 1 | ||
| 18 | + /Kids [ | ||
| 19 | + 3 0 R | ||
| 20 | + ] | ||
| 21 | + /Type /Pages | ||
| 22 | +>> | ||
| 23 | +endobj | ||
| 24 | + | ||
| 25 | +%% Page 1 | ||
| 26 | +%% Original object ID: 3 0 | ||
| 27 | +3 0 obj | ||
| 28 | +<< | ||
| 29 | + /Contents 4 0 R | ||
| 30 | + /MediaBox [ | ||
| 31 | + 0 | ||
| 32 | + 0 | ||
| 33 | + 612 | ||
| 34 | + 792 | ||
| 35 | + ] | ||
| 36 | + /Parent 2 0 R | ||
| 37 | + /Resources << | ||
| 38 | + /Font << | ||
| 39 | + /F1 6 0 R | ||
| 40 | + >> | ||
| 41 | + /ProcSet 7 0 R | ||
| 42 | + >> | ||
| 43 | + /Type /Page | ||
| 44 | +>> | ||
| 45 | +endobj | ||
| 46 | + | ||
| 47 | +%% Contents for page 1 | ||
| 48 | +%% Original object ID: 4 0 | ||
| 49 | +4 0 obj | ||
| 50 | +<< | ||
| 51 | + /Length 5 0 R | ||
| 52 | +>> | ||
| 53 | +stream | ||
| 54 | +BT | ||
| 55 | + /F1 24 Tf | ||
| 56 | + 72 720 Td | ||
| 57 | + (Potato) Tj | ||
| 58 | +ET | ||
| 59 | +endstream | ||
| 60 | +endobj | ||
| 61 | + | ||
| 62 | +5 0 obj | ||
| 63 | +44 | ||
| 64 | +endobj | ||
| 65 | + | ||
| 66 | +%% Original object ID: 6 0 | ||
| 67 | +6 0 obj | ||
| 68 | +<< | ||
| 69 | + /BaseFont /Helvetica | ||
| 70 | + /Encoding /WinAnsiEncoding | ||
| 71 | + /Name /F1 | ||
| 72 | + /Subtype /Type1 | ||
| 73 | + /Type /Font | ||
| 74 | +>> | ||
| 75 | +endobj | ||
| 76 | + | ||
| 77 | +%% Original object ID: 5 0 | ||
| 78 | +7 0 obj | ||
| 79 | +[ | ||
| 80 | |||
| 81 | + /Text | ||
| 82 | +] | ||
| 83 | +endobj | ||
| 84 | + | ||
| 85 | +xref | ||
| 86 | +0 8 | ||
| 87 | +0000000000 65535 f | ||
| 88 | +0000000052 00000 n | ||
| 89 | +0000000201 00000 n | ||
| 90 | +0000000310 00000 n | ||
| 91 | +0000000552 00000 n | ||
| 92 | +0000000651 00000 n | ||
| 93 | +0000000697 00000 n | ||
| 94 | +0000000842 00000 n | ||
| 95 | +trailer << | ||
| 96 | + /Root 1 0 R | ||
| 97 | + /Size 8 | ||
| 98 | + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] | ||
| 99 | +>> | ||
| 100 | +startxref | ||
| 101 | +877 | ||
| 102 | +%%EOF |
qpdf/qtest/qpdf/extensions-none-force-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-none-min-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-force-1.8.5.pdf
0 โ 100644
No preview for this file type
qpdf/qtest/qpdf/extensions-other-force-1.8.5.qdf
0 โ 100644
| 1 | +%PDF-1.8 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +%% Original object ID: 1 0 | ||
| 6 | +1 0 obj | ||
| 7 | +<< | ||
| 8 | + /Extensions << | ||
| 9 | + /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> | ||
| 10 | + /Potato << | ||
| 11 | + /BaseVersion /3.14159 | ||
| 12 | + /ExtensionLevel 16059 | ||
| 13 | + >> | ||
| 14 | + >> | ||
| 15 | + /Pages 2 0 R | ||
| 16 | + /Type /Catalog | ||
| 17 | +>> | ||
| 18 | +endobj | ||
| 19 | + | ||
| 20 | +%% Original object ID: 2 0 | ||
| 21 | +2 0 obj | ||
| 22 | +<< | ||
| 23 | + /Count 1 | ||
| 24 | + /Kids [ | ||
| 25 | + 3 0 R | ||
| 26 | + ] | ||
| 27 | + /Type /Pages | ||
| 28 | +>> | ||
| 29 | +endobj | ||
| 30 | + | ||
| 31 | +%% Page 1 | ||
| 32 | +%% Original object ID: 3 0 | ||
| 33 | +3 0 obj | ||
| 34 | +<< | ||
| 35 | + /Contents 4 0 R | ||
| 36 | + /MediaBox [ | ||
| 37 | + 0 | ||
| 38 | + 0 | ||
| 39 | + 612 | ||
| 40 | + 792 | ||
| 41 | + ] | ||
| 42 | + /Parent 2 0 R | ||
| 43 | + /Resources << | ||
| 44 | + /Font << | ||
| 45 | + /F1 6 0 R | ||
| 46 | + >> | ||
| 47 | + /ProcSet 7 0 R | ||
| 48 | + >> | ||
| 49 | + /Type /Page | ||
| 50 | +>> | ||
| 51 | +endobj | ||
| 52 | + | ||
| 53 | +%% Contents for page 1 | ||
| 54 | +%% Original object ID: 4 0 | ||
| 55 | +4 0 obj | ||
| 56 | +<< | ||
| 57 | + /Length 5 0 R | ||
| 58 | +>> | ||
| 59 | +stream | ||
| 60 | +BT | ||
| 61 | + /F1 24 Tf | ||
| 62 | + 72 720 Td | ||
| 63 | + (Potato) Tj | ||
| 64 | +ET | ||
| 65 | +endstream | ||
| 66 | +endobj | ||
| 67 | + | ||
| 68 | +5 0 obj | ||
| 69 | +44 | ||
| 70 | +endobj | ||
| 71 | + | ||
| 72 | +%% Original object ID: 6 0 | ||
| 73 | +6 0 obj | ||
| 74 | +<< | ||
| 75 | + /BaseFont /Helvetica | ||
| 76 | + /Encoding /WinAnsiEncoding | ||
| 77 | + /Name /F1 | ||
| 78 | + /Subtype /Type1 | ||
| 79 | + /Type /Font | ||
| 80 | +>> | ||
| 81 | +endobj | ||
| 82 | + | ||
| 83 | +%% Original object ID: 7 0 | ||
| 84 | +7 0 obj | ||
| 85 | +[ | ||
| 86 | |||
| 87 | + /Text | ||
| 88 | +] | ||
| 89 | +endobj | ||
| 90 | + | ||
| 91 | +xref | ||
| 92 | +0 8 | ||
| 93 | +0000000000 65535 f | ||
| 94 | +0000000052 00000 n | ||
| 95 | +0000000285 00000 n | ||
| 96 | +0000000394 00000 n | ||
| 97 | +0000000636 00000 n | ||
| 98 | +0000000735 00000 n | ||
| 99 | +0000000781 00000 n | ||
| 100 | +0000000926 00000 n | ||
| 101 | +trailer << | ||
| 102 | + /Root 1 0 R | ||
| 103 | + /Size 8 | ||
| 104 | + /ID [<369e89600ee1a6c4c7e73533610180c2><31415926535897932384626433832795>] | ||
| 105 | +>> | ||
| 106 | +startxref | ||
| 107 | +961 | ||
| 108 | +%%EOF |
qpdf/qtest/qpdf/extensions-other-force-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.6.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.7.1.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.7.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.7.3.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.8.0.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.8.2.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.8.5.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other-min-1.8.out
0 โ 100644
qpdf/qtest/qpdf/extensions-other.pdf
0 โ 100644
| 1 | +%PDF-1.5 | ||
| 2 | +%ยฟรทยขรพ | ||
| 3 | +%QDF-1.0 | ||
| 4 | + | ||
| 5 | +1 0 obj | ||
| 6 | +<< | ||
| 7 | + /Pages 2 0 R | ||
| 8 | + /Type /Catalog | ||
| 9 | + /Extensions << | ||
| 10 | + /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> | ||
| 11 | + >> | ||
| 12 | +>> | ||
| 13 | +endobj | ||
| 14 | + | ||
| 15 | +2 0 obj | ||
| 16 | +<< | ||
| 17 | + /Count 1 | ||
| 18 | + /Kids [ | ||
| 19 | + 3 0 R | ||
| 20 | + ] | ||
| 21 | + /Type /Pages | ||
| 22 | +>> | ||
| 23 | +endobj | ||
| 24 | + | ||
| 25 | +%% Page 1 | ||
| 26 | +3 0 obj | ||
| 27 | +<< | ||
| 28 | + /Contents 4 0 R | ||
| 29 | + /MediaBox [ | ||
| 30 | + 0 | ||
| 31 | + 0 | ||
| 32 | + 612 | ||
| 33 | + 792 | ||
| 34 | + ] | ||
| 35 | + /Parent 2 0 R | ||
| 36 | + /Resources << | ||
| 37 | + /Font << | ||
| 38 | + /F1 6 0 R | ||
| 39 | + >> | ||
| 40 | + /ProcSet 7 0 R | ||
| 41 | + >> | ||
| 42 | + /Type /Page | ||
| 43 | +>> | ||
| 44 | +endobj | ||
| 45 | + | ||
| 46 | +%% Contents for page 1 | ||
| 47 | +4 0 obj | ||
| 48 | +<< | ||
| 49 | + /Length 5 0 R | ||
| 50 | +>> | ||
| 51 | +stream | ||
| 52 | +BT | ||
| 53 | + /F1 24 Tf | ||
| 54 | + 72 720 Td | ||
| 55 | + (Potato) Tj | ||
| 56 | +ET | ||
| 57 | +endstream | ||
| 58 | +endobj | ||
| 59 | + | ||
| 60 | +5 0 obj | ||
| 61 | +44 | ||
| 62 | +endobj | ||
| 63 | + | ||
| 64 | +6 0 obj | ||
| 65 | +<< | ||
| 66 | + /BaseFont /Helvetica | ||
| 67 | + /Encoding /WinAnsiEncoding | ||
| 68 | + /Name /F1 | ||
| 69 | + /Subtype /Type1 | ||
| 70 | + /Type /Font | ||
| 71 | +>> | ||
| 72 | +endobj | ||
| 73 | + | ||
| 74 | +7 0 obj | ||
| 75 | +[ | ||
| 76 | |||
| 77 | + /Text | ||
| 78 | +] | ||
| 79 | +endobj | ||
| 80 | + | ||
| 81 | +xref | ||
| 82 | +0 8 | ||
| 83 | +0000000000 65535 f | ||
| 84 | +0000000025 00000 n | ||
| 85 | +0000000163 00000 n | ||
| 86 | +0000000245 00000 n | ||
| 87 | +0000000460 00000 n | ||
| 88 | +0000000559 00000 n | ||
| 89 | +0000000578 00000 n | ||
| 90 | +0000000696 00000 n | ||
| 91 | +trailer << | ||
| 92 | + /Root 1 0 R | ||
| 93 | + /Size 8 | ||
| 94 | + /ID [<369e89600ee1a6c4c7e73533610180c2><369e89600ee1a6c4c7e73533610180c2>] | ||
| 95 | +>> | ||
| 96 | +startxref | ||
| 97 | +731 | ||
| 98 | +%%EOF |
qpdf/qtest/qpdf/obj0-check.out
| 1 | checking obj0.pdf | 1 | checking obj0.pdf |
| 2 | -PDF Version: 1.3 | ||
| 3 | -File is not encrypted | ||
| 4 | -File is not linearized | ||
| 5 | WARNING: obj0.pdf: file is damaged | 2 | WARNING: obj0.pdf: file is damaged |
| 6 | WARNING: obj0.pdf (object 1 0, file position 77): expected n n obj | 3 | WARNING: obj0.pdf (object 1 0, file position 77): expected n n obj |
| 7 | WARNING: obj0.pdf: Attempting to reconstruct cross-reference table | 4 | WARNING: obj0.pdf: Attempting to reconstruct cross-reference table |
| 5 | +PDF Version: 1.3 | ||
| 6 | +File is not encrypted | ||
| 7 | +File is not linearized |
qpdf/test_driver.cc
| @@ -1126,6 +1126,13 @@ void runtest(int n, char const* filename1, char const* filename2) | @@ -1126,6 +1126,13 @@ void runtest(int n, char const* filename1, char const* filename2) | ||
| 1126 | fwrite(b->getBuffer(), b->getSize(), 1, f); | 1126 | fwrite(b->getBuffer(), b->getSize(), 1, f); |
| 1127 | fclose(f); | 1127 | fclose(f); |
| 1128 | } | 1128 | } |
| 1129 | + else if (n == 34) | ||
| 1130 | + { | ||
| 1131 | + // Look at Extensions dictionary | ||
| 1132 | + std::cout << "version: " << pdf.getPDFVersion() << std::endl | ||
| 1133 | + << "extension level: " << pdf.getExtensionLevel() << std::endl | ||
| 1134 | + << pdf.getRoot().getKey("/Extensions").unparse() << std::endl; | ||
| 1135 | + } | ||
| 1129 | else | 1136 | else |
| 1130 | { | 1137 | { |
| 1131 | throw std::runtime_error(std::string("invalid test ") + | 1138 | throw std::runtime_error(std::string("invalid test ") + |