Change --json-output format

from "qpdf-v2" to "qpdf": [..., ...]
This commit is contained in:
Jay Berkenbilt 2022-07-30 19:29:55 -04:00
parent bb96499b61
commit d01c4f8819
63 changed files with 570 additions and 250 deletions

6
TODO
View File

@ -84,15 +84,13 @@ JSON v2 fixes
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.3",
"pushedinheritedpageresources": false,
"calledgetallpages": false,
"maxobjectid": 10
},
{
"pdfversion": "1.3",
"objects": {
...
}
... objects ...
}
]
}

View File

@ -47,6 +47,7 @@
"bufpl",
"bufsize",
"buildrules",
"calledgetallpages",
"ccase",
"ccitt",
"cdef",
@ -369,6 +370,7 @@
"programfiles",
"programlisting",
"proxied",
"pushedinheritedpageresources",
"putu",
"pval",
"pytest",

View File

@ -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;

View File

@ -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_String> pl_str;
if (this->m->test_json_schema) {

View File

@ -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<std::string> 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";

View File

@ -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:

View File

@ -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

View File

@ -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',

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -1,6 +1,9 @@
{
"qpdf-v2": {
"pdfversion": "1.3",
"maxobjectid": 6
}
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.3",
"maxobjectid": 6
}
]
}

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -1,6 +1,9 @@
{
"qpdf-v2": {
"pdfversion": "1.7",
"objects": false
}
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.7"
},
false
]
}

View File

@ -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

View File

@ -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"
]
}

View File

@ -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

View File

@ -0,0 +1,5 @@
{
"qpdf": {
"potato": "salad"
}
}

View File

@ -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

View File

@ -1,12 +1,15 @@
{
"qpdf-v2": {
"pdfversion": "1.7",
"objects": {
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.7"
},
{
"obj:1 0 R": {
"stream": {
"dict": "quack"
}
}
}
}
]
}

View File

@ -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

View File

@ -1,10 +1,13 @@
{
"qpdf-v2": {
"pdfversion": "1.7",
"objects": {
"qpdf": [
{
"jsonversion": 2,
"pdfversion": "1.7"
},
{
"obj:1 0 R": {
"stream": 3
}
}
}
]
}

View File

@ -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

View File

@ -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
}
}
}
]
}

View File

@ -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

View File

@ -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": {}
}
}
}
]
}

View File

@ -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

View File

@ -1,6 +1,9 @@
{
"qpdf-v2": {
"objects": {
"qpdf": [
{
"jsonversion": 2
},
{
"obj:4 0 R": {
"stream": {
"data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=",
@ -16,5 +19,5 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}

View File

@ -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 @@
}
}
}
}
]
}