From d01c4f8819ea93797784c19ecdd623eb41f2a8b4 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 30 Jul 2022 19:29:55 -0400 Subject: [PATCH] Change --json-output format from "qpdf-v2" to "qpdf": [..., ...] --- TODO | 6 +- cSpell.json | 2 + include/qpdf/QPDF.hh | 3 + libqpdf/QPDFJob.cc | 3 + libqpdf/QPDF_json.cc | 119 ++++++++++++++---- manual/json.rst | 48 +++++-- qpdf/qpdf.testcov | 4 + qpdf/qtest/qpdf-json.test | 2 + qpdf/qtest/qpdf/exp-large-json.json | 15 ++- .../qtest/qpdf/json-bad-data-json-file-v2.out | 15 ++- .../qpdf/json-bad-data-json-inline-v2.out | 15 ++- .../qpdf/json-image-streams-all-file-v2.out | 15 ++- ...json-image-streams-generalized-file-v2.out | 15 ++- ...on-image-streams-generalized-inline-v2.out | 15 ++- .../qpdf/json-image-streams-none-file-v2.out | 15 ++- .../json-image-streams-none-inline-v2.out | 15 ++- ...json-image-streams-specialized-file-v2.out | 15 ++- ...on-image-streams-specialized-inline-v2.out | 15 ++- qpdf/qtest/qpdf/manual-qpdf-json-out.json | 15 ++- qpdf/qtest/qpdf/manual-qpdf-json-pdf.json | 15 ++- qpdf/qtest/qpdf/manual-qpdf-json.json | 25 ++-- qpdf/qtest/qpdf/minimal-json-file-2.out | 15 ++- qpdf/qtest/qpdf/minimal-json-file.out | 15 ++- qpdf/qtest/qpdf/qjson-bad-data.json | 13 +- qpdf/qtest/qpdf/qjson-bad-datafile.json | 13 +- qpdf/qtest/qpdf/qjson-bad-object-key.json | 13 +- qpdf/qtest/qpdf/qjson-bad-object-key.out | 2 +- qpdf/qtest/qpdf/qjson-bad-pdf-version1.json | 13 +- qpdf/qtest/qpdf/qjson-bad-pdf-version1.out | 3 +- qpdf/qtest/qpdf/qjson-bad-pdf-version2.json | 13 +- qpdf/qtest/qpdf/qjson-bad-pdf-version2.out | 3 +- qpdf/qtest/qpdf/qjson-missing-objects.json | 11 +- qpdf/qtest/qpdf/qjson-missing-objects.out | 2 +- qpdf/qtest/qpdf/qjson-missing-trailer.json | 13 +- qpdf/qtest/qpdf/qjson-missing-trailer.out | 2 +- qpdf/qtest/qpdf/qjson-no-pdf-version.json | 10 +- qpdf/qtest/qpdf/qjson-no-pdf-version.out | 3 +- qpdf/qtest/qpdf/qjson-obj-key-errors.json | 13 +- qpdf/qtest/qpdf/qjson-obj-key-errors.out | 12 +- qpdf/qtest/qpdf/qjson-object-not-dict.json | 13 +- qpdf/qtest/qpdf/qjson-object-not-dict.out | 2 +- qpdf/qtest/qpdf/qjson-objects-not-dict.json | 11 +- qpdf/qtest/qpdf/qjson-objects-not-dict.out | 4 +- .../qtest/qpdf/qjson-qpdf-array-too-long.json | 72 +++++++++++ qpdf/qtest/qpdf/qjson-qpdf-array-too-long.out | 2 + qpdf/qtest/qpdf/qjson-qpdf-not-array.json | 5 + qpdf/qtest/qpdf/qjson-qpdf-not-array.out | 5 + .../qpdf/qjson-stream-dict-not-dict.json | 11 +- .../qtest/qpdf/qjson-stream-dict-not-dict.out | 8 +- qpdf/qtest/qpdf/qjson-stream-not-dict.json | 11 +- qpdf/qtest/qpdf/qjson-stream-not-dict.out | 4 +- qpdf/qtest/qpdf/qjson-trailer-not-dict.json | 13 +- qpdf/qtest/qpdf/qjson-trailer-not-dict.out | 2 +- qpdf/qtest/qpdf/qjson-trailer-stream.json | 13 +- qpdf/qtest/qpdf/qjson-trailer-stream.out | 2 +- qpdf/qtest/qpdf/qpdf-json-update-errors.json | 9 +- qpdf/qtest/qpdf/replace-with-stream.json | 13 +- qpdf/qtest/qpdf/test-89.out | 8 +- qpdf/qtest/qpdf/test-90.out | 6 +- qpdf/qtest/qpdf/update-from-json-errors.out | 6 +- qpdf/qtest/qpdf/update-stream-data.json | 13 +- qpdf/qtest/qpdf/update-stream-dict-only.json | 13 +- qpdf/qtest/qpdf/various-updates.json | 13 +- 63 files changed, 570 insertions(+), 250 deletions(-) create mode 100644 qpdf/qtest/qpdf/qjson-qpdf-array-too-long.json create mode 100644 qpdf/qtest/qpdf/qjson-qpdf-array-too-long.out create mode 100644 qpdf/qtest/qpdf/qjson-qpdf-not-array.json create mode 100644 qpdf/qtest/qpdf/qjson-qpdf-not-array.out diff --git a/TODO b/TODO index 61de004d..3830a938 100644 --- a/TODO +++ b/TODO @@ -84,15 +84,13 @@ JSON v2 fixes "qpdf": [ { "jsonversion": 2, + "pdfversion": "1.3", "pushedinheritedpageresources": false, "calledgetallpages": false, "maxobjectid": 10 }, { - "pdfversion": "1.3", - "objects": { - ... - } + ... objects ... } ] } diff --git a/cSpell.json b/cSpell.json index 507ef610..6251d984 100644 --- a/cSpell.json +++ b/cSpell.json @@ -47,6 +47,7 @@ "bufpl", "bufsize", "buildrules", + "calledgetallpages", "ccase", "ccitt", "cdef", @@ -369,6 +370,7 @@ "programfiles", "programlisting", "proxied", + "pushedinheritedpageresources", "putu", "pval", "pytest", diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index 639e16c4..943528bd 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -1072,6 +1072,7 @@ class QPDF st_initial, st_top, st_qpdf, + st_qpdf_meta, st_objects, st_trailer, st_object_top, @@ -1097,7 +1098,9 @@ class QPDF bool errors; bool parse_error; bool saw_qpdf; + bool saw_qpdf_meta; bool saw_objects; + bool saw_json_version; bool saw_pdf_version; bool saw_trailer; state_e state; diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index ae717218..e09c0d74 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -1741,6 +1741,9 @@ QPDFJob::json_out_schema_v1() void QPDFJob::doJSON(QPDF& pdf, Pipeline* p) { + // qpdf guarantees that no new top-level keys whose names start + // with "xdata" will be added. These are reserved for users. + std::string captured_json; std::shared_ptr pl_str; if (this->m->test_json_schema) { diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc index 81f21f8a..9ecb1b31 100644 --- a/libqpdf/QPDF_json.cc +++ b/libqpdf/QPDF_json.cc @@ -226,7 +226,9 @@ QPDF::JSONReactor::JSONReactor( errors(false), parse_error(false), saw_qpdf(false), + saw_qpdf_meta(false), saw_objects(false), + saw_json_version(false), saw_pdf_version(false), saw_trailer(false), state(st_initial), @@ -292,17 +294,21 @@ QPDF::JSONReactor::containerEnd(JSON const& value) QTC::TC("qpdf", "QPDF_json missing qpdf"); error(0, "\"qpdf\" object was not seen"); } else { + if (!this->saw_json_version) { + QTC::TC("qpdf", "QPDF_json missing json version"); + error(0, "\"qpdf[0].jsonversion\" was not seen"); + } if (must_be_complete && !this->saw_pdf_version) { QTC::TC("qpdf", "QPDF_json missing pdf version"); - error(0, "\"qpdf-v2.pdfversion\" was not seen"); + error(0, "\"qpdf[0].pdfversion\" was not seen"); } if (!this->saw_objects) { QTC::TC("qpdf", "QPDF_json missing objects"); - error(0, "\"qpdf-v2.objects\" was not seen"); + error(0, "\"qpdf[1]\" was not seen"); } else { if (must_be_complete && !this->saw_trailer) { QTC::TC("qpdf", "QPDF_json missing trailer"); - error(0, "\"qpdf-v2.objects.trailer\" was not seen"); + error(0, "\"qpdf[1].trailer\" was not seen"); } } } @@ -421,16 +427,22 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) QTC::TC("qpdf", "QPDF_json ignoring in st_ignore"); // ignore } else if (state == st_top) { - if (key == "qpdf-v2") { + if (key == "qpdf") { this->saw_qpdf = true; - nestedState(key, value, st_qpdf); + if (!value.isArray()) { + QTC::TC("qpdf", "QPDF_json qpdf not array"); + error(value.getStart(), "\"qpdf\" must be an array"); + next_state = st_ignore; + parse_error = true; + } else { + next_state = st_qpdf; + } } else { - // Ignore all other fields. We explicitly allow people to - // add other top-level keys for their own use. + // Ignore all other fields. QTC::TC("qpdf", "QPDF_json ignoring unknown top-level key"); next_state = st_ignore; } - } else if (state == st_qpdf) { + } else if (state == st_qpdf_meta) { if (key == "pdfversion") { this->saw_pdf_version = true; bool version_okay = false; @@ -447,9 +459,20 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) QTC::TC("qpdf", "QPDF_json bad pdf version"); error(value.getStart(), "invalid PDF version (must be x.y)"); } - } else if (key == "objects") { - this->saw_objects = true; - nestedState(key, value, st_objects); + } else if (key == "jsonversion") { + this->saw_json_version = true; + bool version_okay = false; + std::string v; + if (value.getNumber(v)) { + std::string version; + if (QUtil::string_to_int(v.c_str()) == 2) { + version_okay = true; + } + } + if (!version_okay) { + QTC::TC("qpdf", "QPDF_json bad json version"); + error(value.getStart(), "invalid JSON version (must be 2)"); + } } else { // ignore unknown keys for forward compatibility and to // skip keys we don't care about like "maxobjectid". @@ -601,6 +624,20 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) bool QPDF::JSONReactor::arrayItem(JSON const& value) { + if (state == st_qpdf) { + if (!this->saw_qpdf_meta) { + this->saw_qpdf_meta = true; + nestedState("qpdf[0]", value, st_qpdf_meta); + } else if (!this->saw_objects) { + this->saw_objects = true; + nestedState("qpdf[1]", value, st_objects); + } else { + QTC::TC("qpdf", "QPDF_json more than two qpdf elements"); + error(value.getStart(), "\"qpdf\" must have two elements"); + next_state = st_ignore; + parse_error = true; + } + } if (state == st_object) { if (!parse_error) { auto tos = object_stack.back(); @@ -771,30 +808,60 @@ QPDF::writeJSON( std::string const& file_prefix, std::set wanted_objects) { + int const depth_outer = 1; + int const depth_top = 1; + int const depth_qpdf = 2; + int const depth_qpdf_inner = 3; + if (version != 2) { throw std::runtime_error( "QPDF::writeJSON: only version 2 is supported"); } bool first = true; if (complete) { - JSON::writeDictionaryOpen(p, first, 0); + JSON::writeDictionaryOpen(p, first, depth_outer); } else { first = first_key; } - JSON::writeDictionaryKey(p, first, "qpdf-v2", 1); + JSON::writeDictionaryKey(p, first, "qpdf", depth_top); bool first_qpdf = true; - JSON::writeDictionaryOpen(p, first_qpdf, 2); - JSON::writeDictionaryItem( - p, first_qpdf, "pdfversion", JSON::makeString(getPDFVersion()), 2); + JSON::writeArrayOpen(p, first_qpdf, depth_top); + JSON::writeNext(p, first_qpdf, depth_qpdf); + bool first_qpdf_inner = true; + JSON::writeDictionaryOpen(p, first_qpdf_inner, depth_qpdf); JSON::writeDictionaryItem( p, - first_qpdf, + first_qpdf_inner, + "jsonversion", + JSON::makeInt(version), + depth_qpdf_inner); + JSON::writeDictionaryItem( + p, + first_qpdf_inner, + "pdfversion", + JSON::makeString(getPDFVersion()), + depth_qpdf_inner); + JSON::writeDictionaryItem( + p, + first_qpdf_inner, + "pushedinheritedpageresources", + JSON::makeBool(everPushedInheritedAttributesToPages()), + depth_qpdf_inner); + JSON::writeDictionaryItem( + p, + first_qpdf_inner, + "calledgetallpages", + JSON::makeBool(everCalledGetAllPages()), + depth_qpdf_inner); + JSON::writeDictionaryItem( + p, + first_qpdf_inner, "maxobjectid", JSON::makeInt(QIntC::to_longlong(getObjectCount())), - 2); - JSON::writeDictionaryKey(p, first_qpdf, "objects", 2); - bool first_object = true; - JSON::writeDictionaryOpen(p, first_object, 2); + depth_qpdf_inner); + JSON::writeDictionaryClose(p, first_qpdf_inner, depth_qpdf); + JSON::writeNext(p, first_qpdf, depth_qpdf); + JSON::writeDictionaryOpen(p, first_qpdf_inner, depth_qpdf); bool all_objects = wanted_objects.empty(); for (auto& obj: getAllObjects()) { std::string key = "obj:" + obj.unparse(); @@ -803,23 +870,23 @@ QPDF::writeJSON( writeJSONStream( version, p, - first_object, + first_qpdf_inner, key, obj, decode_level, json_stream_data, file_prefix); } else { - writeJSONObject(version, p, first_object, key, obj); + writeJSONObject(version, p, first_qpdf_inner, key, obj); } } } if (all_objects || wanted_objects.count("trailer")) { auto trailer = getTrailer(); - writeJSONObject(version, p, first_object, "trailer", trailer); + writeJSONObject(version, p, first_qpdf_inner, "trailer", trailer); } - JSON::writeDictionaryClose(p, first_object, 2); - JSON::writeDictionaryClose(p, first_qpdf, 1); + JSON::writeDictionaryClose(p, first_qpdf_inner, depth_qpdf); + JSON::writeArrayClose(p, first_qpdf, depth_top); if (complete) { JSON::writeDictionaryClose(p, first, 0); *p << "\n"; diff --git a/manual/json.rst b/manual/json.rst index 92a89b6b..0becd405 100644 --- a/manual/json.rst +++ b/manual/json.rst @@ -256,17 +256,34 @@ qpdf JSON Output The format of the JSON written by qpdf's :qpdf:ref:`--json-output` flag or the ``QPDF::writeJSON`` API call is a JSON object consisting -of a single key: ``"qpdf-v2"``. Any other top-level keys are ignored. -While unknown keys in other places are ignored for future -compatibility, in this case, ignoring other top-level keys is an -explicit decision to allow users to include other keys for their own -use. No new top-level keys will be added in JSON version 2. +of a single key: ``"qpdf"``. This may be the only key, or it may be +embedded in the output of ``qpdf --json``. Unknown keys are ignored +for future compatibility. It is guaranteed that qpdf will never add +any keys whose names start with ``xdata``, so users are free to add +their own metadata using keys whose names start with ``xdata`` without +fear of clashing with a future version of qpdf. -The ``"qpdf-v2"`` key points to a JSON object with the following keys: +The ``"qpdf"`` key points to a two-element JSON array. The first element is +a JSON object with the following keys: + +- ``"jsonversion"`` -- a number indicating the JSON version used for + writing. This will always be ``2``. - ``"pdfversion"`` -- a string containing PDF version as indicated in the PDF header (e.g. ``"1.7"``, ``"2.0"``) +- ``pushedinheritedpageresources`` -- a boolean indicating whether + the library pushed inherited resources down to the page level. + Certain library calls cause this to happen, and qpdf needs to know + when reading a JSON file back in whether it should do this as it may + cause certain objects to be renumbered. + +- ``calledgetallpages`` -- a boolean indicating whether + ``getAllPages`` was called prior to writing the JSON output. This + method causes page tree repair to occur, which may renumber some + objects (in very rare cases of corrupted page trees), so qpdf needs + to know this information when reading a JSON file back in. + - ``"maxobjectid"`` -- a number indicating the object ID of the highest numbered object in the file. This is provided to make it easier for software that wants to add new objects to the file as you @@ -280,8 +297,8 @@ The ``"qpdf-v2"`` key points to a JSON object with the following keys: dangling references and says to treat them as nulls. This can happen if objects are removed from a PDF file.) -- ``"objects"`` -- the actual PDF objects as described in - :ref:`json.objects`. +The second element is a JSON object containing the actual PDF objects +as described in :ref:`json.objects`. Note that writing JSON output is done by ``QPDF``, not ``QPDFWriter``. As such, none of the things ``QPDFWriter`` does apply. This includes @@ -302,10 +319,15 @@ qpdf JSON format. .. code-block:: json { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 5, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 5, + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -359,7 +381,7 @@ qpdf JSON format. } } } - } + ] } .. _json.input: diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index bc4c2128..bfd3585f 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -668,3 +668,7 @@ QPDF_json non-trivial null reserved 0 QPDF_json data and datafile 0 QPDF_json no stream data in update mode 0 QPDF_json updating existing stream 0 +QPDF_json qpdf not array 0 +QPDF_json more than two qpdf elements 0 +QPDF_json missing json version 0 +QPDF_json bad json version 0 diff --git a/qpdf/qtest/qpdf-json.test b/qpdf/qtest/qpdf-json.test index 23edda2e..abd9fa49 100644 --- a/qpdf/qtest/qpdf-json.test +++ b/qpdf/qtest/qpdf-json.test @@ -18,6 +18,8 @@ my $n_tests = 0; my @badfiles = ( 'no-qpdf-object', + 'qpdf-not-array', + 'qpdf-array-too-long', 'no-pdf-version', 'top-level-scalar', 'bad-pdf-version1', diff --git a/qpdf/qtest/qpdf/exp-large-json.json b/qpdf/qtest/qpdf/exp-large-json.json index 92f8b4b0..012ab69c 100644 --- a/qpdf/qtest/qpdf/exp-large-json.json +++ b/qpdf/qtest/qpdf/exp-large-json.json @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 604, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 604 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -8444,5 +8449,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-bad-data-json-file-v2.out b/qpdf/qtest/qpdf/json-bad-data-json-file-v2.out index 8b2c825b..d0386ed0 100644 --- a/qpdf/qtest/qpdf/json-bad-data-json-file-v2.out +++ b/qpdf/qtest/qpdf/json-bad-data-json-file-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -71,5 +76,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-bad-data-json-inline-v2.out b/qpdf/qtest/qpdf/json-bad-data-json-inline-v2.out index c90bbf07..72d73f0e 100644 --- a/qpdf/qtest/qpdf/json-bad-data-json-inline-v2.out +++ b/qpdf/qtest/qpdf/json-bad-data-json-inline-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -71,5 +76,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-all-file-v2.out b/qpdf/qtest/qpdf/json-image-streams-all-file-v2.out index 78c5bef8..82f50faa 100644 --- a/qpdf/qtest/qpdf/json-image-streams-all-file-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-all-file-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:12 0 R": { "stream": { "datafile": "auto-12", @@ -36,5 +41,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-generalized-file-v2.out b/qpdf/qtest/qpdf/json-image-streams-generalized-file-v2.out index 78bbdbb2..7b5fc55e 100644 --- a/qpdf/qtest/qpdf/json-image-streams-generalized-file-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-generalized-file-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:12 0 R": { "stream": { "datafile": "auto-12", @@ -38,5 +43,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-generalized-inline-v2.out b/qpdf/qtest/qpdf/json-image-streams-generalized-inline-v2.out index 2830f033..6e3fe192 100644 --- a/qpdf/qtest/qpdf/json-image-streams-generalized-inline-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-generalized-inline-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -457,5 +462,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-none-file-v2.out b/qpdf/qtest/qpdf/json-image-streams-none-file-v2.out index a3f3c3cc..9a9f3b88 100644 --- a/qpdf/qtest/qpdf/json-image-streams-none-file-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-none-file-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:12 0 R": { "stream": { "datafile": "auto-12", @@ -40,5 +45,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-none-inline-v2.out b/qpdf/qtest/qpdf/json-image-streams-none-inline-v2.out index 518ae50a..3ec8671b 100644 --- a/qpdf/qtest/qpdf/json-image-streams-none-inline-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-none-inline-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -478,5 +483,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-specialized-file-v2.out b/qpdf/qtest/qpdf/json-image-streams-specialized-file-v2.out index e09d040f..b2a8a2d5 100644 --- a/qpdf/qtest/qpdf/json-image-streams-specialized-file-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-specialized-file-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:12 0 R": { "stream": { "datafile": "auto-12", @@ -37,5 +42,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/json-image-streams-specialized-inline-v2.out b/qpdf/qtest/qpdf/json-image-streams-specialized-inline-v2.out index 5ee93e2d..8a35a3f4 100644 --- a/qpdf/qtest/qpdf/json-image-streams-specialized-inline-v2.out +++ b/qpdf/qtest/qpdf/json-image-streams-specialized-inline-v2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 30, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 30 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -454,5 +459,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/manual-qpdf-json-out.json b/qpdf/qtest/qpdf/manual-qpdf-json-out.json index 1ad4ddad..b8edda25 100644 --- a/qpdf/qtest/qpdf/manual-qpdf-json-out.json +++ b/qpdf/qtest/qpdf/manual-qpdf-json-out.json @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "2.0", - "maxobjectid": 100, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 100 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -139,5 +144,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json b/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json index afbb696d..9b28f8cf 100644 --- a/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json +++ b/qpdf/qtest/qpdf/manual-qpdf-json-pdf.json @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "2.0", - "maxobjectid": 10, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 10 + }, + { "obj:1 0 R": { "value": { "/Pages": "3 0 R", @@ -146,5 +151,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/manual-qpdf-json.json b/qpdf/qtest/qpdf/manual-qpdf-json.json index 3fc04621..b6c4916c 100644 --- a/qpdf/qtest/qpdf/manual-qpdf-json.json +++ b/qpdf/qtest/qpdf/manual-qpdf-json.json @@ -2,17 +2,20 @@ "comment": [ "We allow and ignore other top-level keys" ], - "qpdf-v2": { - "pdfversion": "2.0", - "maybe-future-key": { - "x": [ - "Lots of times we ignore things", - "for forward-compatibility so we don't have", - "to change the version number if we add stuff", - "in the future" - ] + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "maybe-future-key": { + "x": [ + "Lots of times we ignore things", + "for forward-compatibility so we don't have", + "to change the version number if we add stuff", + "in the future" + ] + } }, - "objects": { + { "obj:3 0 R": { "value": { "/Contents": "4 0 R", @@ -141,5 +144,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/minimal-json-file-2.out b/qpdf/qtest/qpdf/minimal-json-file-2.out index 8114a26f..e8f98d54 100644 --- a/qpdf/qtest/qpdf/minimal-json-file-2.out +++ b/qpdf/qtest/qpdf/minimal-json-file-2.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -65,5 +70,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/minimal-json-file.out b/qpdf/qtest/qpdf/minimal-json-file.out index 520ebe83..2c8ddb39 100644 --- a/qpdf/qtest/qpdf/minimal-json-file.out +++ b/qpdf/qtest/qpdf/minimal-json-file.out @@ -1,8 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "pushedinheritedpageresources": false, + "calledgetallpages": false, + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -65,5 +70,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-bad-data.json b/qpdf/qtest/qpdf/qjson-bad-data.json index 9b8880d4..64ee8050 100644 --- a/qpdf/qtest/qpdf/qjson-bad-data.json +++ b/qpdf/qtest/qpdf/qjson-bad-data.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -64,5 +67,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-bad-datafile.json b/qpdf/qtest/qpdf/qjson-bad-datafile.json index 025f700b..614ea08f 100644 --- a/qpdf/qtest/qpdf/qjson-bad-datafile.json +++ b/qpdf/qtest/qpdf/qjson-bad-datafile.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -64,5 +67,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-bad-object-key.json b/qpdf/qtest/qpdf/qjson-bad-object-key.json index e8637891..1b74d28a 100644 --- a/qpdf/qtest/qpdf/qjson-bad-object-key.json +++ b/qpdf/qtest/qpdf/qjson-bad-object-key.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "potato": { }, "obj:1 0 R": { @@ -66,5 +69,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-bad-object-key.out b/qpdf/qtest/qpdf/qjson-bad-object-key.out index dee225f7..bf339090 100644 --- a/qpdf/qtest/qpdf/qjson-bad-object-key.out +++ b/qpdf/qtest/qpdf/qjson-bad-object-key.out @@ -1,2 +1,2 @@ -WARNING: qjson-bad-object-key.json (offset 97): object key should be "trailer" or "obj:n n R" +WARNING: qjson-bad-object-key.json (offset 123): object key should be "trailer" or "obj:n n R" qpdf: qjson-bad-object-key.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-bad-pdf-version1.json b/qpdf/qtest/qpdf/qjson-bad-pdf-version1.json index e99c26ef..d4c5448c 100644 --- a/qpdf/qtest/qpdf/qjson-bad-pdf-version1.json +++ b/qpdf/qtest/qpdf/qjson-bad-pdf-version1.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "potato", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": "quack", + "pdfversion": "potato", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -64,5 +67,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-bad-pdf-version1.out b/qpdf/qtest/qpdf/qjson-bad-pdf-version1.out index 2f18da41..f364f1a6 100644 --- a/qpdf/qtest/qpdf/qjson-bad-pdf-version1.out +++ b/qpdf/qtest/qpdf/qjson-bad-pdf-version1.out @@ -1,2 +1,3 @@ -WARNING: qjson-bad-pdf-version1.json (offset 35): invalid PDF version (must be x.y) +WARNING: qjson-bad-pdf-version1.json (offset 41): invalid JSON version (must be 2) +WARNING: qjson-bad-pdf-version1.json (offset 70): invalid PDF version (must be x.y) qpdf: qjson-bad-pdf-version1.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-bad-pdf-version2.json b/qpdf/qtest/qpdf/qjson-bad-pdf-version2.json index acc1642a..f70cfb52 100644 --- a/qpdf/qtest/qpdf/qjson-bad-pdf-version2.json +++ b/qpdf/qtest/qpdf/qjson-bad-pdf-version2.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": [], - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 850, + "pdfversion": [], + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -64,5 +67,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-bad-pdf-version2.out b/qpdf/qtest/qpdf/qjson-bad-pdf-version2.out index 3a5086ba..65be40ca 100644 --- a/qpdf/qtest/qpdf/qjson-bad-pdf-version2.out +++ b/qpdf/qtest/qpdf/qjson-bad-pdf-version2.out @@ -1,2 +1,3 @@ -WARNING: qjson-bad-pdf-version2.json (offset 35): invalid PDF version (must be x.y) +WARNING: qjson-bad-pdf-version2.json (offset 41): invalid JSON version (must be 2) +WARNING: qjson-bad-pdf-version2.json (offset 66): invalid PDF version (must be x.y) qpdf: qjson-bad-pdf-version2.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-missing-objects.json b/qpdf/qtest/qpdf/qjson-missing-objects.json index ae287217..a5d6b485 100644 --- a/qpdf/qtest/qpdf/qjson-missing-objects.json +++ b/qpdf/qtest/qpdf/qjson-missing-objects.json @@ -1,6 +1,9 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6 - } + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + } + ] } diff --git a/qpdf/qtest/qpdf/qjson-missing-objects.out b/qpdf/qtest/qpdf/qjson-missing-objects.out index 2692a97b..e5de89df 100644 --- a/qpdf/qtest/qpdf/qjson-missing-objects.out +++ b/qpdf/qtest/qpdf/qjson-missing-objects.out @@ -1,2 +1,2 @@ -WARNING: qjson-missing-objects.json: "qpdf-v2.objects" was not seen +WARNING: qjson-missing-objects.json: "qpdf[1]" was not seen qpdf: qjson-missing-objects.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-missing-trailer.json b/qpdf/qtest/qpdf/qjson-missing-trailer.json index 21050e05..e2fe9a10 100644 --- a/qpdf/qtest/qpdf/qjson-missing-trailer.json +++ b/qpdf/qtest/qpdf/qjson-missing-trailer.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -58,5 +61,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-missing-trailer.out b/qpdf/qtest/qpdf/qjson-missing-trailer.out index 3a4b7910..de3793dd 100644 --- a/qpdf/qtest/qpdf/qjson-missing-trailer.out +++ b/qpdf/qtest/qpdf/qjson-missing-trailer.out @@ -1,2 +1,2 @@ -WARNING: qjson-missing-trailer.json: "qpdf-v2.objects.trailer" was not seen +WARNING: qjson-missing-trailer.json: "qpdf[1].trailer" was not seen qpdf: qjson-missing-trailer.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-no-pdf-version.json b/qpdf/qtest/qpdf/qjson-no-pdf-version.json index 77bfe1ca..53c5a725 100644 --- a/qpdf/qtest/qpdf/qjson-no-pdf-version.json +++ b/qpdf/qtest/qpdf/qjson-no-pdf-version.json @@ -1,7 +1,9 @@ { - "qpdf-v2": { - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -63,5 +65,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-no-pdf-version.out b/qpdf/qtest/qpdf/qjson-no-pdf-version.out index 6a00d76c..a57ffb18 100644 --- a/qpdf/qtest/qpdf/qjson-no-pdf-version.out +++ b/qpdf/qtest/qpdf/qjson-no-pdf-version.out @@ -1,2 +1,3 @@ -WARNING: qjson-no-pdf-version.json: "qpdf-v2.pdfversion" was not seen +WARNING: qjson-no-pdf-version.json: "qpdf[0].jsonversion" was not seen +WARNING: qjson-no-pdf-version.json: "qpdf[0].pdfversion" was not seen qpdf: qjson-no-pdf-version.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-obj-key-errors.json b/qpdf/qtest/qpdf/qjson-obj-key-errors.json index 2adc33d4..627421c8 100644 --- a/qpdf/qtest/qpdf/qjson-obj-key-errors.json +++ b/qpdf/qtest/qpdf/qjson-obj-key-errors.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -55,5 +58,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-obj-key-errors.out b/qpdf/qtest/qpdf/qjson-obj-key-errors.out index e739a2f8..0263f294 100644 --- a/qpdf/qtest/qpdf/qjson-obj-key-errors.out +++ b/qpdf/qtest/qpdf/qjson-obj-key-errors.out @@ -1,7 +1,7 @@ -WARNING: qjson-obj-key-errors.json (obj:2 0 R, offset 218): object must have exactly one of "value" or "stream" -WARNING: qjson-obj-key-errors.json (obj:3 0 R, offset 516): object must have exactly one of "value" or "stream" -WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 684): "stream" is missing "dict" -WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 684): new "stream" must have exactly one of "data" or "datafile" -WARNING: qjson-obj-key-errors.json (obj:5 0 R, offset 774): new "stream" must have exactly one of "data" or "datafile" -WARNING: qjson-obj-key-errors.json (trailer, offset 1152): "trailer" is missing "value" +WARNING: qjson-obj-key-errors.json (obj:2 0 R, offset 244): object must have exactly one of "value" or "stream" +WARNING: qjson-obj-key-errors.json (obj:3 0 R, offset 542): object must have exactly one of "value" or "stream" +WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 710): "stream" is missing "dict" +WARNING: qjson-obj-key-errors.json (obj:4 0 R, offset 710): new "stream" must have exactly one of "data" or "datafile" +WARNING: qjson-obj-key-errors.json (obj:5 0 R, offset 800): new "stream" must have exactly one of "data" or "datafile" +WARNING: qjson-obj-key-errors.json (trailer, offset 1178): "trailer" is missing "value" qpdf: qjson-obj-key-errors.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-object-not-dict.json b/qpdf/qtest/qpdf/qjson-object-not-dict.json index 93357afd..c7f3abc7 100644 --- a/qpdf/qtest/qpdf/qjson-object-not-dict.json +++ b/qpdf/qtest/qpdf/qjson-object-not-dict.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": "potato", "obj:2 0 R": { "value": { @@ -59,5 +62,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-object-not-dict.out b/qpdf/qtest/qpdf/qjson-object-not-dict.out index 1268c83d..5c77c88b 100644 --- a/qpdf/qtest/qpdf/qjson-object-not-dict.out +++ b/qpdf/qtest/qpdf/qjson-object-not-dict.out @@ -1,2 +1,2 @@ -WARNING: qjson-object-not-dict.json (obj:1 0 R, offset 100): "obj:1 0 R" must be a dictionary +WARNING: qjson-object-not-dict.json (obj:1 0 R, offset 126): "obj:1 0 R" must be a dictionary qpdf: qjson-object-not-dict.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-objects-not-dict.json b/qpdf/qtest/qpdf/qjson-objects-not-dict.json index 12870f81..55288a37 100644 --- a/qpdf/qtest/qpdf/qjson-objects-not-dict.json +++ b/qpdf/qtest/qpdf/qjson-objects-not-dict.json @@ -1,6 +1,9 @@ { - "qpdf-v2": { - "pdfversion": "1.7", - "objects": false - } + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.7" + }, + false + ] } diff --git a/qpdf/qtest/qpdf/qjson-objects-not-dict.out b/qpdf/qtest/qpdf/qjson-objects-not-dict.out index b009ef63..219b00e2 100644 --- a/qpdf/qtest/qpdf/qjson-objects-not-dict.out +++ b/qpdf/qtest/qpdf/qjson-objects-not-dict.out @@ -1,3 +1,3 @@ -WARNING: qjson-objects-not-dict.json (offset 58): "objects" must be a dictionary -WARNING: qjson-objects-not-dict.json: "qpdf-v2.objects.trailer" was not seen +WARNING: qjson-objects-not-dict.json (offset 82): "qpdf[1]" must be a dictionary +WARNING: qjson-objects-not-dict.json: "qpdf[1].trailer" was not seen qpdf: qjson-objects-not-dict.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-qpdf-array-too-long.json b/qpdf/qtest/qpdf/qjson-qpdf-array-too-long.json new file mode 100644 index 00000000..ed05b142 --- /dev/null +++ b/qpdf/qtest/qpdf/qjson-qpdf-array-too-long.json @@ -0,0 +1,72 @@ +{ + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { + "obj:1 0 R": { + "value": { + "/Pages": "2 0 R", + "/Type": "/Catalog" + } + }, + "obj:2 0 R": { + "value": { + "/Count": 1, + "/Kids": [ + "3 0 R" + ], + "/Type": "/Pages" + } + }, + "obj:3 0 R": { + "value": { + "/Contents": "4 0 R", + "/MediaBox": [ + 0, + 0, + 612, + 792 + ], + "/Parent": "2 0 R", + "/Resources": { + "/Font": { + "/F1": "6 0 R" + }, + "/ProcSet": "5 0 R" + }, + "/Type": "/Page" + } + }, + "obj:4 0 R": { + "stream": { + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", + "dict": {} + } + }, + "obj:5 0 R": { + "value": [ + "/PDF", + "/Text" + ] + }, + "obj:6 0 R": { + "value": { + "/BaseFont": "/Helvetica", + "/Encoding": "/WinAnsiEncoding", + "/Subtype": "/Type1", + "/Type": "/Font" + } + }, + "trailer": { + "value": { + "/Root": "1 0 R", + "/Size": 7 + } + } + }, + "this doesn't belong here" + ] +} diff --git a/qpdf/qtest/qpdf/qjson-qpdf-array-too-long.out b/qpdf/qtest/qpdf/qjson-qpdf-array-too-long.out new file mode 100644 index 00000000..065286d6 --- /dev/null +++ b/qpdf/qtest/qpdf/qjson-qpdf-array-too-long.out @@ -0,0 +1,2 @@ +WARNING: qjson-qpdf-array-too-long.json (offset 1348): "qpdf" must have two elements +qpdf: qjson-qpdf-array-too-long.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-qpdf-not-array.json b/qpdf/qtest/qpdf/qjson-qpdf-not-array.json new file mode 100644 index 00000000..68846aeb --- /dev/null +++ b/qpdf/qtest/qpdf/qjson-qpdf-not-array.json @@ -0,0 +1,5 @@ +{ + "qpdf": { + "potato": "salad" + } +} diff --git a/qpdf/qtest/qpdf/qjson-qpdf-not-array.out b/qpdf/qtest/qpdf/qjson-qpdf-not-array.out new file mode 100644 index 00000000..3122ba78 --- /dev/null +++ b/qpdf/qtest/qpdf/qjson-qpdf-not-array.out @@ -0,0 +1,5 @@ +WARNING: qjson-qpdf-not-array.json (offset 12): "qpdf" must be an array +WARNING: qjson-qpdf-not-array.json: "qpdf[0].jsonversion" was not seen +WARNING: qjson-qpdf-not-array.json: "qpdf[0].pdfversion" was not seen +WARNING: qjson-qpdf-not-array.json: "qpdf[1]" was not seen +qpdf: qjson-qpdf-not-array.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json b/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json index a34e1a7e..7f68f756 100644 --- a/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json +++ b/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json @@ -1,12 +1,15 @@ { - "qpdf-v2": { - "pdfversion": "1.7", - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.7" + }, + { "obj:1 0 R": { "stream": { "dict": "quack" } } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out b/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out index 39b5207d..a264839f 100644 --- a/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out +++ b/qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out @@ -1,5 +1,5 @@ -WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 118): "stream.dict" must be a dictionary -WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 118): unrecognized string value -WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 98): new "stream" must have exactly one of "data" or "datafile" -WARNING: qjson-stream-dict-not-dict.json: "qpdf-v2.objects.trailer" was not seen +WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 142): "stream.dict" must be a dictionary +WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 142): unrecognized string value +WARNING: qjson-stream-dict-not-dict.json (obj:1 0 R, offset 122): new "stream" must have exactly one of "data" or "datafile" +WARNING: qjson-stream-dict-not-dict.json: "qpdf[1].trailer" was not seen qpdf: qjson-stream-dict-not-dict.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-stream-not-dict.json b/qpdf/qtest/qpdf/qjson-stream-not-dict.json index fedf657f..d6d368e6 100644 --- a/qpdf/qtest/qpdf/qjson-stream-not-dict.json +++ b/qpdf/qtest/qpdf/qjson-stream-not-dict.json @@ -1,10 +1,13 @@ { - "qpdf-v2": { - "pdfversion": "1.7", - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.7" + }, + { "obj:1 0 R": { "stream": 3 } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-stream-not-dict.out b/qpdf/qtest/qpdf/qjson-stream-not-dict.out index 4d492bcf..6a462ff6 100644 --- a/qpdf/qtest/qpdf/qjson-stream-not-dict.out +++ b/qpdf/qtest/qpdf/qjson-stream-not-dict.out @@ -1,3 +1,3 @@ -WARNING: qjson-stream-not-dict.json (obj:1 0 R, offset 99): "stream" must be a dictionary -WARNING: qjson-stream-not-dict.json: "qpdf-v2.objects.trailer" was not seen +WARNING: qjson-stream-not-dict.json (obj:1 0 R, offset 123): "stream" must be a dictionary +WARNING: qjson-stream-not-dict.json: "qpdf[1].trailer" was not seen qpdf: qjson-stream-not-dict.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-trailer-not-dict.json b/qpdf/qtest/qpdf/qjson-trailer-not-dict.json index 0617095e..ee2b1b9f 100644 --- a/qpdf/qtest/qpdf/qjson-trailer-not-dict.json +++ b/qpdf/qtest/qpdf/qjson-trailer-not-dict.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -61,5 +64,5 @@ "value": false } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-trailer-not-dict.out b/qpdf/qtest/qpdf/qjson-trailer-not-dict.out index 5a7ce0e8..3b9d482d 100644 --- a/qpdf/qtest/qpdf/qjson-trailer-not-dict.out +++ b/qpdf/qtest/qpdf/qjson-trailer-not-dict.out @@ -1,2 +1,2 @@ -WARNING: qjson-trailer-not-dict.json (trailer, offset 1243): "trailer.value" must be a dictionary +WARNING: qjson-trailer-not-dict.json (trailer, offset 1269): "trailer.value" must be a dictionary qpdf: qjson-trailer-not-dict.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qjson-trailer-stream.json b/qpdf/qtest/qpdf/qjson-trailer-stream.json index 2b991a74..3e3a8545 100644 --- a/qpdf/qtest/qpdf/qjson-trailer-stream.json +++ b/qpdf/qtest/qpdf/qjson-trailer-stream.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "1.3", - "maxobjectid": 6, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "1.3", + "maxobjectid": 6 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -61,5 +64,5 @@ "stream": {} } } - } + ] } diff --git a/qpdf/qtest/qpdf/qjson-trailer-stream.out b/qpdf/qtest/qpdf/qjson-trailer-stream.out index 94a60873..a625cd6d 100644 --- a/qpdf/qtest/qpdf/qjson-trailer-stream.out +++ b/qpdf/qtest/qpdf/qjson-trailer-stream.out @@ -1,2 +1,2 @@ -WARNING: qjson-trailer-stream.json (trailer, offset 1243): the trailer may not be a stream +WARNING: qjson-trailer-stream.json (trailer, offset 1269): the trailer may not be a stream qpdf: qjson-trailer-stream.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/qpdf-json-update-errors.json b/qpdf/qtest/qpdf/qpdf-json-update-errors.json index 4f699342..4666856d 100644 --- a/qpdf/qtest/qpdf/qpdf-json-update-errors.json +++ b/qpdf/qtest/qpdf/qpdf-json-update-errors.json @@ -1,6 +1,9 @@ { - "qpdf-v2": { - "objects": { + "qpdf": [ + { + "jsonversion": 2 + }, + { "obj:4 0 R": { "stream": { "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", @@ -16,5 +19,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/replace-with-stream.json b/qpdf/qtest/qpdf/replace-with-stream.json index 7004c2a1..0c824707 100644 --- a/qpdf/qtest/qpdf/replace-with-stream.json +++ b/qpdf/qtest/qpdf/replace-with-stream.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "2.0", - "maxobjectid": 9, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "maxobjectid": 9 + }, + { "obj:8 0 R": { "stream": { "data": "bmV3LXN0cmVhbS1oZXJlCg==", @@ -12,5 +15,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/test-89.out b/qpdf/qtest/qpdf/test-89.out index 97d71e1b..417465aa 100644 --- a/qpdf/qtest/qpdf/test-89.out +++ b/qpdf/qtest/qpdf/test-89.out @@ -1,5 +1,5 @@ -WARNING: manual-qpdf-json.json, trailer at offset 1761: operation for array attempted on object of type dictionary: ignoring attempt to append item -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 -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 -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 +WARNING: manual-qpdf-json.json, trailer at offset 1801: operation for array attempted on object of type dictionary: ignoring attempt to append item +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 +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 +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 test 89 done diff --git a/qpdf/qtest/qpdf/test-90.out b/qpdf/qtest/qpdf/test-90.out index 2c535a09..743bff92 100644 --- a/qpdf/qtest/qpdf/test-90.out +++ b/qpdf/qtest/qpdf/test-90.out @@ -1,5 +1,5 @@ -WARNING: various-updates.json, trailer at offset 580: operation for array attempted on object of type dictionary: ignoring attempt to append item -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 -WARNING: various-updates.json, obj:7 0 R at offset 283: operation for integer attempted on object of type array: returning 0 +WARNING: various-updates.json, trailer at offset 606: operation for array attempted on object of type dictionary: ignoring attempt to append item +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 +WARNING: various-updates.json, obj:7 0 R at offset 309: operation for integer attempted on object of type array: returning 0 WARNING: good13.pdf, object 1 0 at offset 19: operation for array attempted on object of type dictionary: ignoring attempt to append item test 90 done diff --git a/qpdf/qtest/qpdf/update-from-json-errors.out b/qpdf/qtest/qpdf/update-from-json-errors.out index 763579c3..530d707d 100644 --- a/qpdf/qtest/qpdf/update-from-json-errors.out +++ b/qpdf/qtest/qpdf/update-from-json-errors.out @@ -1,4 +1,4 @@ -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" -WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 313): unrecognized string value -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" +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" +WARNING: good13.pdf (obj:20 0 R from qpdf-json-update-errors.json, offset 335): unrecognized string value +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" qpdf: qpdf-json-update-errors.json: errors found in JSON diff --git a/qpdf/qtest/qpdf/update-stream-data.json b/qpdf/qtest/qpdf/update-stream-data.json index a650e93f..ef899269 100644 --- a/qpdf/qtest/qpdf/update-stream-data.json +++ b/qpdf/qtest/qpdf/update-stream-data.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "2.0", - "maxobjectid": 9, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "maxobjectid": 9 + }, + { "obj:1 0 R": { "value": { "/Pages": "2 0 R", @@ -16,5 +19,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/update-stream-dict-only.json b/qpdf/qtest/qpdf/update-stream-dict-only.json index bc0a17ce..93ec4af1 100644 --- a/qpdf/qtest/qpdf/update-stream-dict-only.json +++ b/qpdf/qtest/qpdf/update-stream-dict-only.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "2.0", - "maxobjectid": 9, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "maxobjectid": 9 + }, + { "obj:4 0 R": { "stream": { "dict": { @@ -11,5 +14,5 @@ } } } - } + ] } diff --git a/qpdf/qtest/qpdf/various-updates.json b/qpdf/qtest/qpdf/various-updates.json index 80e36465..883eae8c 100644 --- a/qpdf/qtest/qpdf/various-updates.json +++ b/qpdf/qtest/qpdf/various-updates.json @@ -1,8 +1,11 @@ { - "qpdf-v2": { - "pdfversion": "2.0", - "maxobjectid": 9, - "objects": { + "qpdf": [ + { + "jsonversion": 2, + "pdfversion": "2.0", + "maxobjectid": 9 + }, + { "obj:5 0 R": { "value": null }, @@ -35,5 +38,5 @@ } } } - } + ] }