Commit d01c4f8819ea93797784c19ecdd623eb41f2a8b4

Authored by Jay Berkenbilt
1 parent bb96499b

Change --json-output format

from "qpdf-v2" to "qpdf": [..., ...]
Showing 63 changed files with 569 additions and 249 deletions
@@ -84,15 +84,13 @@ JSON v2 fixes @@ -84,15 +84,13 @@ JSON v2 fixes
84 "qpdf": [ 84 "qpdf": [
85 { 85 {
86 "jsonversion": 2, 86 "jsonversion": 2,
  87 + "pdfversion": "1.3",
87 "pushedinheritedpageresources": false, 88 "pushedinheritedpageresources": false,
88 "calledgetallpages": false, 89 "calledgetallpages": false,
89 "maxobjectid": 10 90 "maxobjectid": 10
90 }, 91 },
91 { 92 {
92 - "pdfversion": "1.3",  
93 - "objects": {  
94 - ...  
95 - } 93 + ... objects ...
96 } 94 }
97 ] 95 ]
98 } 96 }
cSpell.json
@@ -47,6 +47,7 @@ @@ -47,6 +47,7 @@
47 "bufpl", 47 "bufpl",
48 "bufsize", 48 "bufsize",
49 "buildrules", 49 "buildrules",
  50 + "calledgetallpages",
50 "ccase", 51 "ccase",
51 "ccitt", 52 "ccitt",
52 "cdef", 53 "cdef",
@@ -369,6 +370,7 @@ @@ -369,6 +370,7 @@
369 "programfiles", 370 "programfiles",
370 "programlisting", 371 "programlisting",
371 "proxied", 372 "proxied",
  373 + "pushedinheritedpageresources",
372 "putu", 374 "putu",
373 "pval", 375 "pval",
374 "pytest", 376 "pytest",
include/qpdf/QPDF.hh
@@ -1072,6 +1072,7 @@ class QPDF @@ -1072,6 +1072,7 @@ class QPDF
1072 st_initial, 1072 st_initial,
1073 st_top, 1073 st_top,
1074 st_qpdf, 1074 st_qpdf,
  1075 + st_qpdf_meta,
1075 st_objects, 1076 st_objects,
1076 st_trailer, 1077 st_trailer,
1077 st_object_top, 1078 st_object_top,
@@ -1097,7 +1098,9 @@ class QPDF @@ -1097,7 +1098,9 @@ class QPDF
1097 bool errors; 1098 bool errors;
1098 bool parse_error; 1099 bool parse_error;
1099 bool saw_qpdf; 1100 bool saw_qpdf;
  1101 + bool saw_qpdf_meta;
1100 bool saw_objects; 1102 bool saw_objects;
  1103 + bool saw_json_version;
1101 bool saw_pdf_version; 1104 bool saw_pdf_version;
1102 bool saw_trailer; 1105 bool saw_trailer;
1103 state_e state; 1106 state_e state;
libqpdf/QPDFJob.cc
@@ -1741,6 +1741,9 @@ QPDFJob::json_out_schema_v1() @@ -1741,6 +1741,9 @@ QPDFJob::json_out_schema_v1()
1741 void 1741 void
1742 QPDFJob::doJSON(QPDF& pdf, Pipeline* p) 1742 QPDFJob::doJSON(QPDF& pdf, Pipeline* p)
1743 { 1743 {
  1744 + // qpdf guarantees that no new top-level keys whose names start
  1745 + // with "xdata" will be added. These are reserved for users.
  1746 +
1744 std::string captured_json; 1747 std::string captured_json;
1745 std::shared_ptr<Pl_String> pl_str; 1748 std::shared_ptr<Pl_String> pl_str;
1746 if (this->m->test_json_schema) { 1749 if (this->m->test_json_schema) {
libqpdf/QPDF_json.cc
@@ -226,7 +226,9 @@ QPDF::JSONReactor::JSONReactor( @@ -226,7 +226,9 @@ QPDF::JSONReactor::JSONReactor(
226 errors(false), 226 errors(false),
227 parse_error(false), 227 parse_error(false),
228 saw_qpdf(false), 228 saw_qpdf(false),
  229 + saw_qpdf_meta(false),
229 saw_objects(false), 230 saw_objects(false),
  231 + saw_json_version(false),
230 saw_pdf_version(false), 232 saw_pdf_version(false),
231 saw_trailer(false), 233 saw_trailer(false),
232 state(st_initial), 234 state(st_initial),
@@ -292,17 +294,21 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value) @@ -292,17 +294,21 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value)
292 QTC::TC("qpdf", "QPDF_json missing qpdf"); 294 QTC::TC("qpdf", "QPDF_json missing qpdf");
293 error(0, "\"qpdf\" object was not seen"); 295 error(0, "\"qpdf\" object was not seen");
294 } else { 296 } else {
  297 + if (!this->saw_json_version) {
  298 + QTC::TC("qpdf", "QPDF_json missing json version");
  299 + error(0, "\"qpdf[0].jsonversion\" was not seen");
  300 + }
295 if (must_be_complete && !this->saw_pdf_version) { 301 if (must_be_complete && !this->saw_pdf_version) {
296 QTC::TC("qpdf", "QPDF_json missing pdf version"); 302 QTC::TC("qpdf", "QPDF_json missing pdf version");
297 - error(0, "\"qpdf-v2.pdfversion\" was not seen"); 303 + error(0, "\"qpdf[0].pdfversion\" was not seen");
298 } 304 }
299 if (!this->saw_objects) { 305 if (!this->saw_objects) {
300 QTC::TC("qpdf", "QPDF_json missing objects"); 306 QTC::TC("qpdf", "QPDF_json missing objects");
301 - error(0, "\"qpdf-v2.objects\" was not seen"); 307 + error(0, "\"qpdf[1]\" was not seen");
302 } else { 308 } else {
303 if (must_be_complete && !this->saw_trailer) { 309 if (must_be_complete && !this->saw_trailer) {
304 QTC::TC("qpdf", "QPDF_json missing trailer"); 310 QTC::TC("qpdf", "QPDF_json missing trailer");
305 - error(0, "\"qpdf-v2.objects.trailer\" was not seen"); 311 + error(0, "\"qpdf[1].trailer\" was not seen");
306 } 312 }
307 } 313 }
308 } 314 }
@@ -421,16 +427,22 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -421,16 +427,22 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
421 QTC::TC("qpdf", "QPDF_json ignoring in st_ignore"); 427 QTC::TC("qpdf", "QPDF_json ignoring in st_ignore");
422 // ignore 428 // ignore
423 } else if (state == st_top) { 429 } else if (state == st_top) {
424 - if (key == "qpdf-v2") { 430 + if (key == "qpdf") {
425 this->saw_qpdf = true; 431 this->saw_qpdf = true;
426 - nestedState(key, value, st_qpdf); 432 + if (!value.isArray()) {
  433 + QTC::TC("qpdf", "QPDF_json qpdf not array");
  434 + error(value.getStart(), "\"qpdf\" must be an array");
  435 + next_state = st_ignore;
  436 + parse_error = true;
  437 + } else {
  438 + next_state = st_qpdf;
  439 + }
427 } else { 440 } else {
428 - // Ignore all other fields. We explicitly allow people to  
429 - // add other top-level keys for their own use. 441 + // Ignore all other fields.
430 QTC::TC("qpdf", "QPDF_json ignoring unknown top-level key"); 442 QTC::TC("qpdf", "QPDF_json ignoring unknown top-level key");
431 next_state = st_ignore; 443 next_state = st_ignore;
432 } 444 }
433 - } else if (state == st_qpdf) { 445 + } else if (state == st_qpdf_meta) {
434 if (key == "pdfversion") { 446 if (key == "pdfversion") {
435 this->saw_pdf_version = true; 447 this->saw_pdf_version = true;
436 bool version_okay = false; 448 bool version_okay = false;
@@ -447,9 +459,20 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -447,9 +459,20 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
447 QTC::TC("qpdf", "QPDF_json bad pdf version"); 459 QTC::TC("qpdf", "QPDF_json bad pdf version");
448 error(value.getStart(), "invalid PDF version (must be x.y)"); 460 error(value.getStart(), "invalid PDF version (must be x.y)");
449 } 461 }
450 - } else if (key == "objects") {  
451 - this->saw_objects = true;  
452 - nestedState(key, value, st_objects); 462 + } else if (key == "jsonversion") {
  463 + this->saw_json_version = true;
  464 + bool version_okay = false;
  465 + std::string v;
  466 + if (value.getNumber(v)) {
  467 + std::string version;
  468 + if (QUtil::string_to_int(v.c_str()) == 2) {
  469 + version_okay = true;
  470 + }
  471 + }
  472 + if (!version_okay) {
  473 + QTC::TC("qpdf", "QPDF_json bad json version");
  474 + error(value.getStart(), "invalid JSON version (must be 2)");
  475 + }
453 } else { 476 } else {
454 // ignore unknown keys for forward compatibility and to 477 // ignore unknown keys for forward compatibility and to
455 // skip keys we don't care about like "maxobjectid". 478 // skip keys we don't care about like "maxobjectid".
@@ -601,6 +624,20 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -601,6 +624,20 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
601 bool 624 bool
602 QPDF::JSONReactor::arrayItem(JSON const& value) 625 QPDF::JSONReactor::arrayItem(JSON const& value)
603 { 626 {
  627 + if (state == st_qpdf) {
  628 + if (!this->saw_qpdf_meta) {
  629 + this->saw_qpdf_meta = true;
  630 + nestedState("qpdf[0]", value, st_qpdf_meta);
  631 + } else if (!this->saw_objects) {
  632 + this->saw_objects = true;
  633 + nestedState("qpdf[1]", value, st_objects);
  634 + } else {
  635 + QTC::TC("qpdf", "QPDF_json more than two qpdf elements");
  636 + error(value.getStart(), "\"qpdf\" must have two elements");
  637 + next_state = st_ignore;
  638 + parse_error = true;
  639 + }
  640 + }
604 if (state == st_object) { 641 if (state == st_object) {
605 if (!parse_error) { 642 if (!parse_error) {
606 auto tos = object_stack.back(); 643 auto tos = object_stack.back();
@@ -771,30 +808,60 @@ QPDF::writeJSON( @@ -771,30 +808,60 @@ QPDF::writeJSON(
771 std::string const& file_prefix, 808 std::string const& file_prefix,
772 std::set<std::string> wanted_objects) 809 std::set<std::string> wanted_objects)
773 { 810 {
  811 + int const depth_outer = 1;
  812 + int const depth_top = 1;
  813 + int const depth_qpdf = 2;
  814 + int const depth_qpdf_inner = 3;
  815 +
774 if (version != 2) { 816 if (version != 2) {
775 throw std::runtime_error( 817 throw std::runtime_error(
776 "QPDF::writeJSON: only version 2 is supported"); 818 "QPDF::writeJSON: only version 2 is supported");
777 } 819 }
778 bool first = true; 820 bool first = true;
779 if (complete) { 821 if (complete) {
780 - JSON::writeDictionaryOpen(p, first, 0); 822 + JSON::writeDictionaryOpen(p, first, depth_outer);
781 } else { 823 } else {
782 first = first_key; 824 first = first_key;
783 } 825 }
784 - JSON::writeDictionaryKey(p, first, "qpdf-v2", 1); 826 + JSON::writeDictionaryKey(p, first, "qpdf", depth_top);
785 bool first_qpdf = true; 827 bool first_qpdf = true;
786 - JSON::writeDictionaryOpen(p, first_qpdf, 2); 828 + JSON::writeArrayOpen(p, first_qpdf, depth_top);
  829 + JSON::writeNext(p, first_qpdf, depth_qpdf);
  830 + bool first_qpdf_inner = true;
  831 + JSON::writeDictionaryOpen(p, first_qpdf_inner, depth_qpdf);
787 JSON::writeDictionaryItem( 832 JSON::writeDictionaryItem(
788 - p, first_qpdf, "pdfversion", JSON::makeString(getPDFVersion()), 2); 833 + p,
  834 + first_qpdf_inner,
  835 + "jsonversion",
  836 + JSON::makeInt(version),
  837 + depth_qpdf_inner);
  838 + JSON::writeDictionaryItem(
  839 + p,
  840 + first_qpdf_inner,
  841 + "pdfversion",
  842 + JSON::makeString(getPDFVersion()),
  843 + depth_qpdf_inner);
  844 + JSON::writeDictionaryItem(
  845 + p,
  846 + first_qpdf_inner,
  847 + "pushedinheritedpageresources",
  848 + JSON::makeBool(everPushedInheritedAttributesToPages()),
  849 + depth_qpdf_inner);
  850 + JSON::writeDictionaryItem(
  851 + p,
  852 + first_qpdf_inner,
  853 + "calledgetallpages",
  854 + JSON::makeBool(everCalledGetAllPages()),
  855 + depth_qpdf_inner);
789 JSON::writeDictionaryItem( 856 JSON::writeDictionaryItem(
790 p, 857 p,
791 - first_qpdf, 858 + first_qpdf_inner,
792 "maxobjectid", 859 "maxobjectid",
793 JSON::makeInt(QIntC::to_longlong(getObjectCount())), 860 JSON::makeInt(QIntC::to_longlong(getObjectCount())),
794 - 2);  
795 - JSON::writeDictionaryKey(p, first_qpdf, "objects", 2);  
796 - bool first_object = true;  
797 - JSON::writeDictionaryOpen(p, first_object, 2); 861 + depth_qpdf_inner);
  862 + JSON::writeDictionaryClose(p, first_qpdf_inner, depth_qpdf);
  863 + JSON::writeNext(p, first_qpdf, depth_qpdf);
  864 + JSON::writeDictionaryOpen(p, first_qpdf_inner, depth_qpdf);
798 bool all_objects = wanted_objects.empty(); 865 bool all_objects = wanted_objects.empty();
799 for (auto& obj: getAllObjects()) { 866 for (auto& obj: getAllObjects()) {
800 std::string key = "obj:" + obj.unparse(); 867 std::string key = "obj:" + obj.unparse();
@@ -803,23 +870,23 @@ QPDF::writeJSON( @@ -803,23 +870,23 @@ QPDF::writeJSON(
803 writeJSONStream( 870 writeJSONStream(
804 version, 871 version,
805 p, 872 p,
806 - first_object, 873 + first_qpdf_inner,
807 key, 874 key,
808 obj, 875 obj,
809 decode_level, 876 decode_level,
810 json_stream_data, 877 json_stream_data,
811 file_prefix); 878 file_prefix);
812 } else { 879 } else {
813 - writeJSONObject(version, p, first_object, key, obj); 880 + writeJSONObject(version, p, first_qpdf_inner, key, obj);
814 } 881 }
815 } 882 }
816 } 883 }
817 if (all_objects || wanted_objects.count("trailer")) { 884 if (all_objects || wanted_objects.count("trailer")) {
818 auto trailer = getTrailer(); 885 auto trailer = getTrailer();
819 - writeJSONObject(version, p, first_object, "trailer", trailer); 886 + writeJSONObject(version, p, first_qpdf_inner, "trailer", trailer);
820 } 887 }
821 - JSON::writeDictionaryClose(p, first_object, 2);  
822 - JSON::writeDictionaryClose(p, first_qpdf, 1); 888 + JSON::writeDictionaryClose(p, first_qpdf_inner, depth_qpdf);
  889 + JSON::writeArrayClose(p, first_qpdf, depth_top);
823 if (complete) { 890 if (complete) {
824 JSON::writeDictionaryClose(p, first, 0); 891 JSON::writeDictionaryClose(p, first, 0);
825 *p << "\n"; 892 *p << "\n";
manual/json.rst
@@ -256,17 +256,34 @@ qpdf JSON Output @@ -256,17 +256,34 @@ qpdf JSON Output
256 256
257 The format of the JSON written by qpdf's :qpdf:ref:`--json-output` 257 The format of the JSON written by qpdf's :qpdf:ref:`--json-output`
258 flag or the ``QPDF::writeJSON`` API call is a JSON object consisting 258 flag or the ``QPDF::writeJSON`` API call is a JSON object consisting
259 -of a single key: ``"qpdf-v2"``. Any other top-level keys are ignored.  
260 -While unknown keys in other places are ignored for future  
261 -compatibility, in this case, ignoring other top-level keys is an  
262 -explicit decision to allow users to include other keys for their own  
263 -use. No new top-level keys will be added in JSON version 2. 259 +of a single key: ``"qpdf"``. This may be the only key, or it may be
  260 +embedded in the output of ``qpdf --json``. Unknown keys are ignored
  261 +for future compatibility. It is guaranteed that qpdf will never add
  262 +any keys whose names start with ``xdata``, so users are free to add
  263 +their own metadata using keys whose names start with ``xdata`` without
  264 +fear of clashing with a future version of qpdf.
264 265
265 -The ``"qpdf-v2"`` key points to a JSON object with the following keys: 266 +The ``"qpdf"`` key points to a two-element JSON array. The first element is
  267 +a JSON object with the following keys:
  268 +
  269 +- ``"jsonversion"`` -- a number indicating the JSON version used for
  270 + writing. This will always be ``2``.
266 271
267 - ``"pdfversion"`` -- a string containing PDF version as indicated in 272 - ``"pdfversion"`` -- a string containing PDF version as indicated in
268 the PDF header (e.g. ``"1.7"``, ``"2.0"``) 273 the PDF header (e.g. ``"1.7"``, ``"2.0"``)
269 274
  275 +- ``pushedinheritedpageresources`` -- a boolean indicating whether
  276 + the library pushed inherited resources down to the page level.
  277 + Certain library calls cause this to happen, and qpdf needs to know
  278 + when reading a JSON file back in whether it should do this as it may
  279 + cause certain objects to be renumbered.
  280 +
  281 +- ``calledgetallpages`` -- a boolean indicating whether
  282 + ``getAllPages`` was called prior to writing the JSON output. This
  283 + method causes page tree repair to occur, which may renumber some
  284 + objects (in very rare cases of corrupted page trees), so qpdf needs
  285 + to know this information when reading a JSON file back in.
  286 +
270 - ``"maxobjectid"`` -- a number indicating the object ID of the 287 - ``"maxobjectid"`` -- a number indicating the object ID of the
271 highest numbered object in the file. This is provided to make it 288 highest numbered object in the file. This is provided to make it
272 easier for software that wants to add new objects to the file as you 289 easier for software that wants to add new objects to the file as you
@@ -280,8 +297,8 @@ The ``&quot;qpdf-v2&quot;`` key points to a JSON object with the following keys: @@ -280,8 +297,8 @@ The ``&quot;qpdf-v2&quot;`` key points to a JSON object with the following keys:
280 dangling references and says to treat them as nulls. This can happen 297 dangling references and says to treat them as nulls. This can happen
281 if objects are removed from a PDF file.) 298 if objects are removed from a PDF file.)
282 299
283 -- ``"objects"`` -- the actual PDF objects as described in  
284 - :ref:`json.objects`. 300 +The second element is a JSON object containing the actual PDF objects
  301 +as described in :ref:`json.objects`.
285 302
286 Note that writing JSON output is done by ``QPDF``, not ``QPDFWriter``. 303 Note that writing JSON output is done by ``QPDF``, not ``QPDFWriter``.
287 As such, none of the things ``QPDFWriter`` does apply. This includes 304 As such, none of the things ``QPDFWriter`` does apply. This includes
@@ -302,10 +319,15 @@ qpdf JSON format. @@ -302,10 +319,15 @@ qpdf JSON format.
302 .. code-block:: json 319 .. code-block:: json
303 320
304 { 321 {
305 - "qpdf-v2": {  
306 - "pdfversion": "1.3",  
307 - "maxobjectid": 5,  
308 - "objects": { 322 + "qpdf": [
  323 + {
  324 + "jsonversion": 2,
  325 + "pdfversion": "1.3",
  326 + "pushedinheritedpageresources": false,
  327 + "calledgetallpages": false,
  328 + "maxobjectid": 5,
  329 + },
  330 + {
309 "obj:1 0 R": { 331 "obj:1 0 R": {
310 "value": { 332 "value": {
311 "/Pages": "2 0 R", 333 "/Pages": "2 0 R",
@@ -359,7 +381,7 @@ qpdf JSON format. @@ -359,7 +381,7 @@ qpdf JSON format.
359 } 381 }
360 } 382 }
361 } 383 }
362 - } 384 + ]
363 } 385 }
364 386
365 .. _json.input: 387 .. _json.input:
qpdf/qpdf.testcov
@@ -668,3 +668,7 @@ QPDF_json non-trivial null reserved 0 @@ -668,3 +668,7 @@ QPDF_json non-trivial null reserved 0
668 QPDF_json data and datafile 0 668 QPDF_json data and datafile 0
669 QPDF_json no stream data in update mode 0 669 QPDF_json no stream data in update mode 0
670 QPDF_json updating existing stream 0 670 QPDF_json updating existing stream 0
  671 +QPDF_json qpdf not array 0
  672 +QPDF_json more than two qpdf elements 0
  673 +QPDF_json missing json version 0
  674 +QPDF_json bad json version 0
qpdf/qtest/qpdf-json.test
@@ -18,6 +18,8 @@ my $n_tests = 0; @@ -18,6 +18,8 @@ my $n_tests = 0;
18 18
19 my @badfiles = ( 19 my @badfiles = (
20 'no-qpdf-object', 20 'no-qpdf-object',
  21 + 'qpdf-not-array',
  22 + 'qpdf-array-too-long',
21 'no-pdf-version', 23 'no-pdf-version',
22 'top-level-scalar', 24 'top-level-scalar',
23 'bad-pdf-version1', 25 'bad-pdf-version1',
qpdf/qtest/qpdf/exp-large-json.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 604,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 604
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -8444,5 +8449,5 @@ @@ -8444,5 +8449,5 @@
8444 } 8449 }
8445 } 8450 }
8446 } 8451 }
8447 - } 8452 + ]
8448 } 8453 }
qpdf/qtest/qpdf/json-bad-data-json-file-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 6
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -71,5 +76,5 @@ @@ -71,5 +76,5 @@
71 } 76 }
72 } 77 }
73 } 78 }
74 - } 79 + ]
75 } 80 }
qpdf/qtest/qpdf/json-bad-data-json-inline-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 6
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -71,5 +76,5 @@ @@ -71,5 +76,5 @@
71 } 76 }
72 } 77 }
73 } 78 }
74 - } 79 + ]
75 } 80 }
qpdf/qtest/qpdf/json-image-streams-all-file-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:12 0 R": { 11 "obj:12 0 R": {
7 "stream": { 12 "stream": {
8 "datafile": "auto-12", 13 "datafile": "auto-12",
@@ -36,5 +41,5 @@ @@ -36,5 +41,5 @@
36 } 41 }
37 } 42 }
38 } 43 }
39 - } 44 + ]
40 } 45 }
qpdf/qtest/qpdf/json-image-streams-generalized-file-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:12 0 R": { 11 "obj:12 0 R": {
7 "stream": { 12 "stream": {
8 "datafile": "auto-12", 13 "datafile": "auto-12",
@@ -38,5 +43,5 @@ @@ -38,5 +43,5 @@
38 } 43 }
39 } 44 }
40 } 45 }
41 - } 46 + ]
42 } 47 }
qpdf/qtest/qpdf/json-image-streams-generalized-inline-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -457,5 +462,5 @@ @@ -457,5 +462,5 @@
457 } 462 }
458 } 463 }
459 } 464 }
460 - } 465 + ]
461 } 466 }
qpdf/qtest/qpdf/json-image-streams-none-file-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:12 0 R": { 11 "obj:12 0 R": {
7 "stream": { 12 "stream": {
8 "datafile": "auto-12", 13 "datafile": "auto-12",
@@ -40,5 +45,5 @@ @@ -40,5 +45,5 @@
40 } 45 }
41 } 46 }
42 } 47 }
43 - } 48 + ]
44 } 49 }
qpdf/qtest/qpdf/json-image-streams-none-inline-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -478,5 +483,5 @@ @@ -478,5 +483,5 @@
478 } 483 }
479 } 484 }
480 } 485 }
481 - } 486 + ]
482 } 487 }
qpdf/qtest/qpdf/json-image-streams-specialized-file-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:12 0 R": { 11 "obj:12 0 R": {
7 "stream": { 12 "stream": {
8 "datafile": "auto-12", 13 "datafile": "auto-12",
@@ -37,5 +42,5 @@ @@ -37,5 +42,5 @@
37 } 42 }
38 } 43 }
39 } 44 }
40 - } 45 + ]
41 } 46 }
qpdf/qtest/qpdf/json-image-streams-specialized-inline-v2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 30,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 30
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -454,5 +459,5 @@ @@ -454,5 +459,5 @@
454 } 459 }
455 } 460 }
456 } 461 }
457 - } 462 + ]
458 } 463 }
qpdf/qtest/qpdf/manual-qpdf-json-out.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "2.0",  
4 - "maxobjectid": 100,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "2.0",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 100
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -139,5 +144,5 @@ @@ -139,5 +144,5 @@
139 } 144 }
140 } 145 }
141 } 146 }
142 - } 147 + ]
143 } 148 }
qpdf/qtest/qpdf/manual-qpdf-json-pdf.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "2.0",  
4 - "maxobjectid": 10,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "2.0",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 10
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "3 0 R", 13 "/Pages": "3 0 R",
@@ -146,5 +151,5 @@ @@ -146,5 +151,5 @@
146 } 151 }
147 } 152 }
148 } 153 }
149 - } 154 + ]
150 } 155 }
qpdf/qtest/qpdf/manual-qpdf-json.json
@@ -2,17 +2,20 @@ @@ -2,17 +2,20 @@
2 "comment": [ 2 "comment": [
3 "We allow and ignore other top-level keys" 3 "We allow and ignore other top-level keys"
4 ], 4 ],
5 - "qpdf-v2": {  
6 - "pdfversion": "2.0",  
7 - "maybe-future-key": {  
8 - "x": [  
9 - "Lots of times we ignore things",  
10 - "for forward-compatibility so we don't have",  
11 - "to change the version number if we add stuff",  
12 - "in the future"  
13 - ] 5 + "qpdf": [
  6 + {
  7 + "jsonversion": 2,
  8 + "pdfversion": "2.0",
  9 + "maybe-future-key": {
  10 + "x": [
  11 + "Lots of times we ignore things",
  12 + "for forward-compatibility so we don't have",
  13 + "to change the version number if we add stuff",
  14 + "in the future"
  15 + ]
  16 + }
14 }, 17 },
15 - "objects": { 18 + {
16 "obj:3 0 R": { 19 "obj:3 0 R": {
17 "value": { 20 "value": {
18 "/Contents": "4 0 R", 21 "/Contents": "4 0 R",
@@ -141,5 +144,5 @@ @@ -141,5 +144,5 @@
141 } 144 }
142 } 145 }
143 } 146 }
144 - } 147 + ]
145 } 148 }
qpdf/qtest/qpdf/minimal-json-file-2.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 6
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -65,5 +70,5 @@ @@ -65,5 +70,5 @@
65 } 70 }
66 } 71 }
67 } 72 }
68 - } 73 + ]
69 } 74 }
qpdf/qtest/qpdf/minimal-json-file.out
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "pushedinheritedpageresources": false,
  7 + "calledgetallpages": false,
  8 + "maxobjectid": 6
  9 + },
  10 + {
6 "obj:1 0 R": { 11 "obj:1 0 R": {
7 "value": { 12 "value": {
8 "/Pages": "2 0 R", 13 "/Pages": "2 0 R",
@@ -65,5 +70,5 @@ @@ -65,5 +70,5 @@
65 } 70 }
66 } 71 }
67 } 72 }
68 - } 73 + ]
69 } 74 }
qpdf/qtest/qpdf/qjson-bad-data.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -64,5 +67,5 @@ @@ -64,5 +67,5 @@
64 } 67 }
65 } 68 }
66 } 69 }
67 - } 70 + ]
68 } 71 }
qpdf/qtest/qpdf/qjson-bad-datafile.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -64,5 +67,5 @@ @@ -64,5 +67,5 @@
64 } 67 }
65 } 68 }
66 } 69 }
67 - } 70 + ]
68 } 71 }
qpdf/qtest/qpdf/qjson-bad-object-key.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "potato": { 9 "potato": {
7 }, 10 },
8 "obj:1 0 R": { 11 "obj:1 0 R": {
@@ -66,5 +69,5 @@ @@ -66,5 +69,5 @@
66 } 69 }
67 } 70 }
68 } 71 }
69 - } 72 + ]
70 } 73 }
qpdf/qtest/qpdf/qjson-bad-object-key.out
1 -WARNING: qjson-bad-object-key.json (offset 97): object key should be "trailer" or "obj:n n R" 1 +WARNING: qjson-bad-object-key.json (offset 123): object key should be "trailer" or "obj:n n R"
2 qpdf: qjson-bad-object-key.json: errors found in JSON 2 qpdf: qjson-bad-object-key.json: errors found in JSON
qpdf/qtest/qpdf/qjson-bad-pdf-version1.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "potato",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": "quack",
  5 + "pdfversion": "potato",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -64,5 +67,5 @@ @@ -64,5 +67,5 @@
64 } 67 }
65 } 68 }
66 } 69 }
67 - } 70 + ]
68 } 71 }
qpdf/qtest/qpdf/qjson-bad-pdf-version1.out
1 -WARNING: qjson-bad-pdf-version1.json (offset 35): invalid PDF version (must be x.y) 1 +WARNING: qjson-bad-pdf-version1.json (offset 41): invalid JSON version (must be 2)
  2 +WARNING: qjson-bad-pdf-version1.json (offset 70): invalid PDF version (must be x.y)
2 qpdf: qjson-bad-pdf-version1.json: errors found in JSON 3 qpdf: qjson-bad-pdf-version1.json: errors found in JSON
qpdf/qtest/qpdf/qjson-bad-pdf-version2.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": [],  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 850,
  5 + "pdfversion": [],
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -64,5 +67,5 @@ @@ -64,5 +67,5 @@
64 } 67 }
65 } 68 }
66 } 69 }
67 - } 70 + ]
68 } 71 }
qpdf/qtest/qpdf/qjson-bad-pdf-version2.out
1 -WARNING: qjson-bad-pdf-version2.json (offset 35): invalid PDF version (must be x.y) 1 +WARNING: qjson-bad-pdf-version2.json (offset 41): invalid JSON version (must be 2)
  2 +WARNING: qjson-bad-pdf-version2.json (offset 66): invalid PDF version (must be x.y)
2 qpdf: qjson-bad-pdf-version2.json: errors found in JSON 3 qpdf: qjson-bad-pdf-version2.json: errors found in JSON
qpdf/qtest/qpdf/qjson-missing-objects.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6  
5 - } 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + }
  8 + ]
6 } 9 }
qpdf/qtest/qpdf/qjson-missing-objects.out
1 -WARNING: qjson-missing-objects.json: "qpdf-v2.objects" was not seen 1 +WARNING: qjson-missing-objects.json: "qpdf[1]" was not seen
2 qpdf: qjson-missing-objects.json: errors found in JSON 2 qpdf: qjson-missing-objects.json: errors found in JSON
qpdf/qtest/qpdf/qjson-missing-trailer.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -58,5 +61,5 @@ @@ -58,5 +61,5 @@
58 } 61 }
59 } 62 }
60 } 63 }
61 - } 64 + ]
62 } 65 }
qpdf/qtest/qpdf/qjson-missing-trailer.out
1 -WARNING: qjson-missing-trailer.json: "qpdf-v2.objects.trailer" was not seen 1 +WARNING: qjson-missing-trailer.json: "qpdf[1].trailer" was not seen
2 qpdf: qjson-missing-trailer.json: errors found in JSON 2 qpdf: qjson-missing-trailer.json: errors found in JSON
qpdf/qtest/qpdf/qjson-no-pdf-version.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "maxobjectid": 6,  
4 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "maxobjectid": 6
  5 + },
  6 + {
5 "obj:1 0 R": { 7 "obj:1 0 R": {
6 "value": { 8 "value": {
7 "/Pages": "2 0 R", 9 "/Pages": "2 0 R",
@@ -63,5 +65,5 @@ @@ -63,5 +65,5 @@
63 } 65 }
64 } 66 }
65 } 67 }
66 - } 68 + ]
67 } 69 }
qpdf/qtest/qpdf/qjson-no-pdf-version.out
1 -WARNING: qjson-no-pdf-version.json: "qpdf-v2.pdfversion" was not seen 1 +WARNING: qjson-no-pdf-version.json: "qpdf[0].jsonversion" was not seen
  2 +WARNING: qjson-no-pdf-version.json: "qpdf[0].pdfversion" was not seen
2 qpdf: qjson-no-pdf-version.json: errors found in JSON 3 qpdf: qjson-no-pdf-version.json: errors found in JSON
qpdf/qtest/qpdf/qjson-obj-key-errors.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -55,5 +58,5 @@ @@ -55,5 +58,5 @@
55 } 58 }
56 } 59 }
57 } 60 }
58 - } 61 + ]
59 } 62 }
qpdf/qtest/qpdf/qjson-obj-key-errors.out
1 -WARNING: qjson-obj-key-errors.json (obj:2 0 R, offset 218): object must have exactly one of "value" or "stream"  
2 -WARNING: qjson-obj-key-errors.json (obj:3 0 R, offset 516): object must have exactly one of "value" or "stream"  
3 -WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 684): "stream" is missing "dict"  
4 -WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 684): new "stream" must have exactly one of "data" or "datafile"  
5 -WARNING: qjson-obj-key-errors.json (obj:5 0 R, offset 774): new "stream" must have exactly one of "data" or "datafile"  
6 -WARNING: qjson-obj-key-errors.json (trailer, offset 1152): "trailer" is missing "value" 1 +WARNING: qjson-obj-key-errors.json (obj:2 0 R, offset 244): object must have exactly one of "value" or "stream"
  2 +WARNING: qjson-obj-key-errors.json (obj:3 0 R, offset 542): object must have exactly one of "value" or "stream"
  3 +WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 710): "stream" is missing "dict"
  4 +WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 710): new "stream" must have exactly one of "data" or "datafile"
  5 +WARNING: qjson-obj-key-errors.json (obj:5 0 R, offset 800): new "stream" must have exactly one of "data" or "datafile"
  6 +WARNING: qjson-obj-key-errors.json (trailer, offset 1178): "trailer" is missing "value"
7 qpdf: qjson-obj-key-errors.json: errors found in JSON 7 qpdf: qjson-obj-key-errors.json: errors found in JSON
qpdf/qtest/qpdf/qjson-object-not-dict.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": "potato", 9 "obj:1 0 R": "potato",
7 "obj:2 0 R": { 10 "obj:2 0 R": {
8 "value": { 11 "value": {
@@ -59,5 +62,5 @@ @@ -59,5 +62,5 @@
59 } 62 }
60 } 63 }
61 } 64 }
62 - } 65 + ]
63 } 66 }
qpdf/qtest/qpdf/qjson-object-not-dict.out
1 -WARNING: qjson-object-not-dict.json (obj:1 0 R, offset 100): "obj:1 0 R" must be a dictionary 1 +WARNING: qjson-object-not-dict.json (obj:1 0 R, offset 126): "obj:1 0 R" must be a dictionary
2 qpdf: qjson-object-not-dict.json: errors found in JSON 2 qpdf: qjson-object-not-dict.json: errors found in JSON
qpdf/qtest/qpdf/qjson-objects-not-dict.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.7",  
4 - "objects": false  
5 - } 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.7"
  6 + },
  7 + false
  8 + ]
6 } 9 }
qpdf/qtest/qpdf/qjson-objects-not-dict.out
1 -WARNING: qjson-objects-not-dict.json (offset 58): "objects" must be a dictionary  
2 -WARNING: qjson-objects-not-dict.json: "qpdf-v2.objects.trailer" was not seen 1 +WARNING: qjson-objects-not-dict.json (offset 82): "qpdf[1]" must be a dictionary
  2 +WARNING: qjson-objects-not-dict.json: "qpdf[1].trailer" was not seen
3 qpdf: qjson-objects-not-dict.json: errors found in JSON 3 qpdf: qjson-objects-not-dict.json: errors found in JSON
qpdf/qtest/qpdf/qjson-qpdf-array-too-long.json 0 โ†’ 100644
  1 +{
  2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
  9 + "obj:1 0 R": {
  10 + "value": {
  11 + "/Pages": "2 0 R",
  12 + "/Type": "/Catalog"
  13 + }
  14 + },
  15 + "obj:2 0 R": {
  16 + "value": {
  17 + "/Count": 1,
  18 + "/Kids": [
  19 + "3 0 R"
  20 + ],
  21 + "/Type": "/Pages"
  22 + }
  23 + },
  24 + "obj:3 0 R": {
  25 + "value": {
  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": "5 0 R"
  39 + },
  40 + "/Type": "/Page"
  41 + }
  42 + },
  43 + "obj:4 0 R": {
  44 + "stream": {
  45 + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
  46 + "dict": {}
  47 + }
  48 + },
  49 + "obj:5 0 R": {
  50 + "value": [
  51 + "/PDF",
  52 + "/Text"
  53 + ]
  54 + },
  55 + "obj:6 0 R": {
  56 + "value": {
  57 + "/BaseFont": "/Helvetica",
  58 + "/Encoding": "/WinAnsiEncoding",
  59 + "/Subtype": "/Type1",
  60 + "/Type": "/Font"
  61 + }
  62 + },
  63 + "trailer": {
  64 + "value": {
  65 + "/Root": "1 0 R",
  66 + "/Size": 7
  67 + }
  68 + }
  69 + },
  70 + "this doesn't belong here"
  71 + ]
  72 +}
qpdf/qtest/qpdf/qjson-qpdf-array-too-long.out 0 โ†’ 100644
  1 +WARNING: qjson-qpdf-array-too-long.json (offset 1348): "qpdf" must have two elements
  2 +qpdf: qjson-qpdf-array-too-long.json: errors found in JSON
qpdf/qtest/qpdf/qjson-qpdf-not-array.json 0 โ†’ 100644
  1 +{
  2 + "qpdf": {
  3 + "potato": "salad"
  4 + }
  5 +}
qpdf/qtest/qpdf/qjson-qpdf-not-array.out 0 โ†’ 100644
  1 +WARNING: qjson-qpdf-not-array.json (offset 12): "qpdf" must be an array
  2 +WARNING: qjson-qpdf-not-array.json: "qpdf[0].jsonversion" was not seen
  3 +WARNING: qjson-qpdf-not-array.json: "qpdf[0].pdfversion" was not seen
  4 +WARNING: qjson-qpdf-not-array.json: "qpdf[1]" was not seen
  5 +qpdf: qjson-qpdf-not-array.json: errors found in JSON
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.7",  
4 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.7"
  6 + },
  7 + {
5 "obj:1 0 R": { 8 "obj:1 0 R": {
6 "stream": { 9 "stream": {
7 "dict": "quack" 10 "dict": "quack"
8 } 11 }
9 } 12 }
10 } 13 }
11 - } 14 + ]
12 } 15 }
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out
1 -WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 118): "stream.dict" must be a dictionary  
2 -WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 118): unrecognized string value  
3 -WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 98): new "stream" must have exactly one of "data" or "datafile"  
4 -WARNING: qjson-stream-dict-not-dict.json: "qpdf-v2.objects.trailer" was not seen 1 +WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 142): "stream.dict" must be a dictionary
  2 +WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 142): unrecognized string value
  3 +WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 122): new "stream" must have exactly one of "data" or "datafile"
  4 +WARNING: qjson-stream-dict-not-dict.json: "qpdf[1].trailer" was not seen
5 qpdf: qjson-stream-dict-not-dict.json: errors found in JSON 5 qpdf: qjson-stream-dict-not-dict.json: errors found in JSON
qpdf/qtest/qpdf/qjson-stream-not-dict.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.7",  
4 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.7"
  6 + },
  7 + {
5 "obj:1 0 R": { 8 "obj:1 0 R": {
6 "stream": 3 9 "stream": 3
7 } 10 }
8 } 11 }
9 - } 12 + ]
10 } 13 }
qpdf/qtest/qpdf/qjson-stream-not-dict.out
1 -WARNING: qjson-stream-not-dict.json (obj:1 0 R, offset 99): "stream" must be a dictionary  
2 -WARNING: qjson-stream-not-dict.json: "qpdf-v2.objects.trailer" was not seen 1 +WARNING: qjson-stream-not-dict.json (obj:1 0 R, offset 123): "stream" must be a dictionary
  2 +WARNING: qjson-stream-not-dict.json: "qpdf[1].trailer" was not seen
3 qpdf: qjson-stream-not-dict.json: errors found in JSON 3 qpdf: qjson-stream-not-dict.json: errors found in JSON
qpdf/qtest/qpdf/qjson-trailer-not-dict.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -61,5 +64,5 @@ @@ -61,5 +64,5 @@
61 "value": false 64 "value": false
62 } 65 }
63 } 66 }
64 - } 67 + ]
65 } 68 }
qpdf/qtest/qpdf/qjson-trailer-not-dict.out
1 -WARNING: qjson-trailer-not-dict.json (trailer, offset 1243): "trailer.value" must be a dictionary 1 +WARNING: qjson-trailer-not-dict.json (trailer, offset 1269): "trailer.value" must be a dictionary
2 qpdf: qjson-trailer-not-dict.json: errors found in JSON 2 qpdf: qjson-trailer-not-dict.json: errors found in JSON
qpdf/qtest/qpdf/qjson-trailer-stream.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "1.3",  
4 - "maxobjectid": 6,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "1.3",
  6 + "maxobjectid": 6
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -61,5 +64,5 @@ @@ -61,5 +64,5 @@
61 "stream": {} 64 "stream": {}
62 } 65 }
63 } 66 }
64 - } 67 + ]
65 } 68 }
qpdf/qtest/qpdf/qjson-trailer-stream.out
1 -WARNING: qjson-trailer-stream.json (trailer, offset 1243): the trailer may not be a stream 1 +WARNING: qjson-trailer-stream.json (trailer, offset 1269): the trailer may not be a stream
2 qpdf: qjson-trailer-stream.json: errors found in JSON 2 qpdf: qjson-trailer-stream.json: errors found in JSON
qpdf/qtest/qpdf/qpdf-json-update-errors.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2
  5 + },
  6 + {
4 "obj:4 0 R": { 7 "obj:4 0 R": {
5 "stream": { 8 "stream": {
6 "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", 9 "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
@@ -16,5 +19,5 @@ @@ -16,5 +19,5 @@
16 } 19 }
17 } 20 }
18 } 21 }
19 - } 22 + ]
20 } 23 }
qpdf/qtest/qpdf/replace-with-stream.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "2.0",  
4 - "maxobjectid": 9,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "2.0",
  6 + "maxobjectid": 9
  7 + },
  8 + {
6 "obj:8 0 R": { 9 "obj:8 0 R": {
7 "stream": { 10 "stream": {
8 "data": "bmV3LXN0cmVhbS1oZXJlCg==", 11 "data": "bmV3LXN0cmVhbS1oZXJlCg==",
@@ -12,5 +15,5 @@ @@ -12,5 +15,5 @@
12 } 15 }
13 } 16 }
14 } 17 }
15 - } 18 + ]
16 } 19 }
qpdf/qtest/qpdf/test-89.out
1 -WARNING: manual-qpdf-json.json, trailer at offset 1761: operation for array attempted on object of type dictionary: ignoring attempt to append item  
2 -WARNING: manual-qpdf-json.json, obj:1 0 R at offset 1079: operation for array attempted on object of type dictionary: ignoring attempt to append item  
3 -WARNING: manual-qpdf-json.json, obj:5 0 R at offset 1404: operation for dictionary attempted on object of type array: ignoring key replacement request  
4 -WARNING: manual-qpdf-json.json, obj:5 0 R at offset 1416: operation for dictionary attempted on object of type name: ignoring key replacement request 1 +WARNING: manual-qpdf-json.json, trailer at offset 1801: operation for array attempted on object of type dictionary: ignoring attempt to append item
  2 +WARNING: manual-qpdf-json.json, obj:1 0 R at offset 1119: operation for array attempted on object of type dictionary: ignoring attempt to append item
  3 +WARNING: manual-qpdf-json.json, obj:5 0 R at offset 1444: operation for dictionary attempted on object of type array: ignoring key replacement request
  4 +WARNING: manual-qpdf-json.json, obj:5 0 R at offset 1456: operation for dictionary attempted on object of type name: ignoring key replacement request
5 test 89 done 5 test 89 done
qpdf/qtest/qpdf/test-90.out
1 -WARNING: various-updates.json, trailer at offset 580: operation for array attempted on object of type dictionary: ignoring attempt to append item  
2 -WARNING: various-updates.json, obj:7 0 R at offset 171: operation for array attempted on object of type dictionary: ignoring attempt to append item  
3 -WARNING: various-updates.json, obj:7 0 R at offset 283: operation for integer attempted on object of type array: returning 0 1 +WARNING: various-updates.json, trailer at offset 606: operation for array attempted on object of type dictionary: ignoring attempt to append item
  2 +WARNING: various-updates.json, obj:7 0 R at offset 197: operation for array attempted on object of type dictionary: ignoring attempt to append item
  3 +WARNING: various-updates.json, obj:7 0 R at offset 309: operation for integer attempted on object of type array: returning 0
4 WARNING: good13.pdf, object 1 0 at offset 19: operation for array attempted on object of type dictionary: ignoring attempt to append item 4 WARNING: good13.pdf, object 1 0 at offset 19: operation for array attempted on object of type dictionary: ignoring attempt to append item
5 test 90 done 5 test 90 done
qpdf/qtest/qpdf/update-from-json-errors.out
1 -WARNING: good13.pdf (obj:4 0 R from qpdf-json-update-errors.json, offset 73): existing "stream" may at most one of "data" or "datafile"  
2 -WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 313): unrecognized string value  
3 -WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 271): new "stream" must have exactly one of "data" or "datafile" 1 +WARNING: good13.pdf (obj:4 0 R from qpdf-json-update-errors.json, offset 95): existing "stream" may at most one of "data" or "datafile"
  2 +WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 335): unrecognized string value
  3 +WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 293): new "stream" must have exactly one of "data" or "datafile"
4 qpdf: qpdf-json-update-errors.json: errors found in JSON 4 qpdf: qpdf-json-update-errors.json: errors found in JSON
qpdf/qtest/qpdf/update-stream-data.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "2.0",  
4 - "maxobjectid": 9,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "2.0",
  6 + "maxobjectid": 9
  7 + },
  8 + {
6 "obj:1 0 R": { 9 "obj:1 0 R": {
7 "value": { 10 "value": {
8 "/Pages": "2 0 R", 11 "/Pages": "2 0 R",
@@ -16,5 +19,5 @@ @@ -16,5 +19,5 @@
16 } 19 }
17 } 20 }
18 } 21 }
19 - } 22 + ]
20 } 23 }
qpdf/qtest/qpdf/update-stream-dict-only.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "2.0",  
4 - "maxobjectid": 9,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "2.0",
  6 + "maxobjectid": 9
  7 + },
  8 + {
6 "obj:4 0 R": { 9 "obj:4 0 R": {
7 "stream": { 10 "stream": {
8 "dict": { 11 "dict": {
@@ -11,5 +14,5 @@ @@ -11,5 +14,5 @@
11 } 14 }
12 } 15 }
13 } 16 }
14 - } 17 + ]
15 } 18 }
qpdf/qtest/qpdf/various-updates.json
1 { 1 {
2 - "qpdf-v2": {  
3 - "pdfversion": "2.0",  
4 - "maxobjectid": 9,  
5 - "objects": { 2 + "qpdf": [
  3 + {
  4 + "jsonversion": 2,
  5 + "pdfversion": "2.0",
  6 + "maxobjectid": 9
  7 + },
  8 + {
6 "obj:5 0 R": { 9 "obj:5 0 R": {
7 "value": null 10 "value": null
8 }, 11 },
@@ -35,5 +38,5 @@ @@ -35,5 +38,5 @@
35 } 38 }
36 } 39 }
37 } 40 }
38 - } 41 + ]
39 } 42 }