Commit 774584163ff3d310e7c932e2a6f63b590cb736ac

Authored by Jay Berkenbilt
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&amp; version) @@ -183,10 +195,22 @@ QPDFWriter::setMinimumPDFVersion(std::string const&amp; 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&amp; version) @@ -194,12 +218,24 @@ QPDFWriter::setMinimumPDFVersion(std::string const&amp; 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&amp; qpdf) @@ -476,7 +512,8 @@ QPDFWriter::copyEncryptionParameters(QPDF&amp; 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-&gt;runtest(&quot;new stream&quot;, @@ -111,6 +111,55 @@ $td-&gt;runtest(&quot;new stream&quot;,
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-&gt;runtest(&quot;remove page we don&#39;t have&quot;, @@ -147,6 +196,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;,
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-&gt;runtest(&quot;avoid respecification of password&quot;, @@ -513,6 +564,7 @@ $td-&gt;runtest(&quot;avoid respecification of password&quot;,
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-&gt;runtest(&quot;basic qpdf from scratch&quot;, @@ -524,6 +576,7 @@ $td-&gt;runtest(&quot;basic qpdf from scratch&quot;,
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-&gt;runtest(&quot;copy objects error&quot;, @@ -546,6 +599,7 @@ $td-&gt;runtest(&quot;copy objects error&quot;,
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
  1 +version: 1.3
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.6.out 0 โ†’ 100644
  1 +version: 1.6
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 1
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 1 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 /URL (http://something.adobe.com) >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-force-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> >>
  4 +test 34 done
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 + /PDF
  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
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 /URL (http://something.adobe.com) >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.6.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 /URL (http://something.adobe.com) >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 /URL (http://something.adobe.com) >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 /URL (http://something.adobe.com) >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-min-1.8.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.3.out 0 โ†’ 100644
  1 +version: 1.3
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.6.out 0 โ†’ 100644
  1 +version: 1.6
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 1
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 1 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-force-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
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 + /PDF
  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
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.6.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-adbe-other-min-1.8.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
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 + /PDF
  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 + /PDF
  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
  1 +version: 1.3
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.6.out 0 โ†’ 100644
  1 +version: 1.6
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 1
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 1 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-force-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> >>
  4 +test 34 done
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 + /PDF
  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
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.3.out 0 โ†’ 100644
  1 +version: 1.3
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.6.out 0 โ†’ 100644
  1 +version: 1.6
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 1
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 1 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-none-min-1.8.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +null
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.3.out 0 โ†’ 100644
  1 +version: 1.3
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.6.out 0 โ†’ 100644
  1 +version: 1.6
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 1
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 1 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-force-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
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 + /PDF
  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
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.3.out 0 โ†’ 100644
  1 +version: 1.5
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.6.out 0 โ†’ 100644
  1 +version: 1.6
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.7.1.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 1
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 1 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.7.2.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.7.3.out 0 โ†’ 100644
  1 +version: 1.7
  2 +extension level: 3
  3 +<< /ADBE << /BaseVersion /1.7 /ExtensionLevel 3 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.8.0.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.8.2.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 2
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 2 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.8.5.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 5
  3 +<< /ADBE << /BaseVersion /1.8 /ExtensionLevel 5 >> /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
qpdf/qtest/qpdf/extensions-other-min-1.8.out 0 โ†’ 100644
  1 +version: 1.8
  2 +extension level: 0
  3 +<< /Potato << /BaseVersion /3.14159 /ExtensionLevel 16059 >> >>
  4 +test 34 done
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 + /PDF
  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 ") +