mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Implement top-level qpdf json parsing
This commit is contained in:
parent
8d42eb2632
commit
7fa5d1773b
7
TODO
7
TODO
@ -54,6 +54,13 @@ Soon: Break ground on "Document-level work"
|
||||
Output JSON v2
|
||||
==============
|
||||
|
||||
Try to never flatten pages tree. Make sure we do something reasonable
|
||||
with pages tree repair. The problem is that if pages tree repair is
|
||||
done as a side effect of running --json, the qpdf part of the json may
|
||||
contain object numbers that aren't there. Maybe we need to indicate
|
||||
whether pages tree repair has been done in the json, but this would
|
||||
have to be known early in parsing, which is a problem.
|
||||
|
||||
General things to remember:
|
||||
|
||||
* Make sure all the information from --check and other informational
|
||||
|
@ -998,6 +998,7 @@ class QPDF
|
||||
class JSONReactor: public JSON::Reactor
|
||||
{
|
||||
public:
|
||||
JSONReactor(QPDF&, bool must_be_complete);
|
||||
virtual ~JSONReactor() = default;
|
||||
virtual void dictionaryStart() override;
|
||||
virtual void arrayStart() override;
|
||||
@ -1006,6 +1007,32 @@ class QPDF
|
||||
virtual bool
|
||||
dictionaryItem(std::string const& key, JSON const& value) override;
|
||||
virtual bool arrayItem(JSON const& value) override;
|
||||
|
||||
private:
|
||||
enum state_e {
|
||||
st_initial,
|
||||
st_top,
|
||||
st_ignore,
|
||||
st_qpdf,
|
||||
st_objects_top,
|
||||
st_trailer_top,
|
||||
st_object_top,
|
||||
st_stream,
|
||||
st_object,
|
||||
};
|
||||
|
||||
void containerStart();
|
||||
void nestedState(std::string const& key, JSON const& value, state_e);
|
||||
|
||||
QPDF& pdf;
|
||||
bool must_be_complete;
|
||||
bool saw_qpdf;
|
||||
bool saw_json_version;
|
||||
bool saw_pdf_version;
|
||||
bool saw_trailer;
|
||||
state_e state;
|
||||
state_e next_state;
|
||||
std::vector<state_e> state_stack;
|
||||
};
|
||||
friend class JSONReactor;
|
||||
|
||||
|
@ -1,42 +1,218 @@
|
||||
#include <qpdf/QPDF.hh>
|
||||
|
||||
#include <qpdf/FileInputSource.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <regex>
|
||||
|
||||
namespace
|
||||
{
|
||||
class JSONExc: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
JSONExc(JSON const& value, std::string const& msg) :
|
||||
std::runtime_error(
|
||||
"offset " + QUtil::uint_to_string(value.getStart()) + ": " +
|
||||
msg)
|
||||
{
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static std::regex PDF_VERSION_RE("^\\d+\\.\\d+$");
|
||||
static std::regex OBJ_KEY_RE("^obj:(\\d+) (\\d+) R$");
|
||||
|
||||
QPDF::JSONReactor::JSONReactor(QPDF& pdf, bool must_be_complete) :
|
||||
pdf(pdf),
|
||||
must_be_complete(must_be_complete),
|
||||
saw_qpdf(false),
|
||||
saw_json_version(false),
|
||||
saw_pdf_version(false),
|
||||
saw_trailer(false),
|
||||
state(st_initial),
|
||||
next_state(st_top)
|
||||
{
|
||||
state_stack.push_back(st_initial);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::JSONReactor::containerStart()
|
||||
{
|
||||
state_stack.push_back(state);
|
||||
state = next_state;
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::JSONReactor::dictionaryStart()
|
||||
{
|
||||
// QXXXXQ
|
||||
containerStart();
|
||||
// QXXXQ
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::JSONReactor::arrayStart()
|
||||
{
|
||||
// QXXXXQ
|
||||
containerStart();
|
||||
if (state == st_top) {
|
||||
QTC::TC("qpdf", "QPDF_json top-level array");
|
||||
throw std::runtime_error("QPDF JSON must be a dictionary");
|
||||
}
|
||||
// QXXXQ
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::JSONReactor::containerEnd(JSON const& value)
|
||||
{
|
||||
// QXXXXQ
|
||||
state = state_stack.back();
|
||||
state_stack.pop_back();
|
||||
if (state == st_initial) {
|
||||
if (!this->saw_qpdf) {
|
||||
QTC::TC("qpdf", "QPDF_json missing qpdf");
|
||||
throw std::runtime_error("\"qpdf\" object was not seen");
|
||||
}
|
||||
if (!this->saw_json_version) {
|
||||
QTC::TC("qpdf", "QPDF_json missing json version");
|
||||
throw std::runtime_error("\"qpdf.jsonversion\" was not seen");
|
||||
}
|
||||
if (must_be_complete && !this->saw_pdf_version) {
|
||||
QTC::TC("qpdf", "QPDF_json missing pdf version");
|
||||
throw std::runtime_error("\"qpdf.pdfversion\" was not seen");
|
||||
}
|
||||
if (must_be_complete && !this->saw_trailer) {
|
||||
/// QTC::TC("qpdf", "QPDF_json missing trailer");
|
||||
throw std::runtime_error("\"qpdf.objects.trailer\" was not seen");
|
||||
}
|
||||
}
|
||||
|
||||
// QXXXQ
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::JSONReactor::topLevelScalar()
|
||||
{
|
||||
// QXXXXQ
|
||||
QTC::TC("qpdf", "QPDF_json top-level scalar");
|
||||
throw std::runtime_error("QPDF JSON must be a dictionary");
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::JSONReactor::nestedState(
|
||||
std::string const& key, JSON const& value, state_e next)
|
||||
{
|
||||
// Use this method when the next state is for processing a nested
|
||||
// dictionary.
|
||||
if (!value.isDictionary()) {
|
||||
throw JSONExc(value, "\"" + key + "\" must be a dictionary");
|
||||
}
|
||||
this->next_state = next;
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
|
||||
{
|
||||
// QXXXXQ
|
||||
if (state == st_ignore) {
|
||||
// ignore
|
||||
} else if (state == st_top) {
|
||||
if (key == "qpdf") {
|
||||
this->saw_qpdf = true;
|
||||
nestedState(key, value, st_qpdf);
|
||||
} else {
|
||||
// Ignore all other fields for forward compatibility.
|
||||
// Don't use nestedState since this can be any type.
|
||||
next_state = st_ignore;
|
||||
}
|
||||
} else if (state == st_qpdf) {
|
||||
if (key == "jsonversion") {
|
||||
this->saw_json_version = true;
|
||||
std::string v;
|
||||
if (!(value.getNumber(v) && (v == "2"))) {
|
||||
QTC::TC("qpdf", "QPDF_json bad json version");
|
||||
throw JSONExc(value, "only JSON version 2 is supported");
|
||||
}
|
||||
} else if (key == "pdfversion") {
|
||||
this->saw_pdf_version = true;
|
||||
bool version_okay = false;
|
||||
std::string v;
|
||||
if (value.getString(v)) {
|
||||
std::smatch m;
|
||||
if (std::regex_match(v, m, PDF_VERSION_RE)) {
|
||||
version_okay = true;
|
||||
this->pdf.m->pdf_version = v;
|
||||
}
|
||||
}
|
||||
if (!version_okay) {
|
||||
QTC::TC("qpdf", "QPDF_json bad pdf version");
|
||||
throw JSONExc(value, "invalid PDF version (must be x.y)");
|
||||
}
|
||||
} else if (key == "objects") {
|
||||
nestedState(key, value, st_objects_top);
|
||||
} else {
|
||||
// ignore unknown keys for forward compatibility
|
||||
}
|
||||
} else if (state == st_objects_top) {
|
||||
std::smatch m;
|
||||
if (key == "trailer") {
|
||||
this->saw_trailer = true;
|
||||
nestedState(key, value, st_trailer_top);
|
||||
// QXXXQ
|
||||
} else if (std::regex_match(key, m, OBJ_KEY_RE)) {
|
||||
nestedState(key, value, st_object_top);
|
||||
// QXXXQ
|
||||
} else {
|
||||
QTC::TC("qpdf", "QPDF_json bad object key");
|
||||
throw JSONExc(
|
||||
value, "object key should be \"trailer\" or \"obj:n n R\"");
|
||||
}
|
||||
} else if (state == st_object_top) {
|
||||
if (key == "value") {
|
||||
// Don't use nestedState since this can have any type.
|
||||
next_state = st_object;
|
||||
// QXXXQ
|
||||
} else if (key == "stream") {
|
||||
nestedState(key, value, st_stream);
|
||||
// QXXXQ
|
||||
} else {
|
||||
// Ignore unknown keys for forward compatibility
|
||||
}
|
||||
} else if (state == st_trailer_top) {
|
||||
if (key == "value") {
|
||||
// The trailer must be a dictionary, so we can use nestedState.
|
||||
nestedState("trailer.value", value, st_object);
|
||||
// QXXXQ
|
||||
} else if (key == "stream") {
|
||||
QTC::TC("qpdf", "QPDF_json trailer stream");
|
||||
throw JSONExc(value, "the trailer may not be a stream");
|
||||
} else {
|
||||
// Ignore unknown keys for forward compatibility
|
||||
}
|
||||
} else if (state == st_stream) {
|
||||
if (key == "dict") {
|
||||
// Since a stream dictionary must be a dictionary, we can
|
||||
// use nestedState to transition to st_value.
|
||||
nestedState("stream.dict", value, st_object);
|
||||
// QXXXQ
|
||||
} else if (key == "data") {
|
||||
// QXXXQ
|
||||
} else if (key == "datafile") {
|
||||
// QXXXQ
|
||||
} else {
|
||||
// Ignore unknown keys for forward compatibility.
|
||||
next_state = st_ignore;
|
||||
}
|
||||
} else if (state == st_object) {
|
||||
// QXXXQ
|
||||
} else {
|
||||
throw std::logic_error(
|
||||
"QPDF_json: unknown state " + QUtil::int_to_string(state));
|
||||
}
|
||||
|
||||
// QXXXQ
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF::JSONReactor::arrayItem(JSON const& value)
|
||||
{
|
||||
// QXXXXQ
|
||||
// QXXXQ
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -65,7 +241,12 @@ QPDF::updateFromJSON(std::shared_ptr<InputSource> is)
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::importJSON(std::shared_ptr<InputSource>, bool must_be_complete)
|
||||
QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete)
|
||||
{
|
||||
// QXXXQ
|
||||
JSONReactor reactor(*this, must_be_complete);
|
||||
try {
|
||||
JSON::parse(*is, &reactor);
|
||||
} catch (std::runtime_error& e) {
|
||||
throw std::runtime_error(is->getName() + ": " + e.what());
|
||||
}
|
||||
}
|
||||
|
@ -650,3 +650,12 @@ QPDFJob json encrypt duplicate key length 0
|
||||
QPDFJob json encrypt missing password 0
|
||||
QPDFJob json pages no file 0
|
||||
qpdf-c called qpdf_empty_pdf 0
|
||||
QPDF_json missing qpdf 0
|
||||
QPDF_json missing json version 0
|
||||
QPDF_json missing pdf version 0
|
||||
QPDF_json top-level scalar 0
|
||||
QPDF_json bad json version 0
|
||||
QPDF_json bad pdf version 0
|
||||
QPDF_json top-level array 0
|
||||
QPDF_json bad object key 0
|
||||
QPDF_json trailer stream 0
|
||||
|
50
qpdf/qtest/qpdf-json.test
Normal file
50
qpdf/qtest/qpdf-json.test
Normal file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env perl
|
||||
require 5.008;
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
unshift(@INC, '.');
|
||||
require qpdf_test_helpers;
|
||||
|
||||
chdir("qpdf") or die "chdir testdir failed: $!\n";
|
||||
|
||||
require TestDriver;
|
||||
|
||||
cleanup();
|
||||
|
||||
my $td = new TestDriver('qpdf-json');
|
||||
|
||||
my $n_tests = 0;
|
||||
|
||||
my @badfiles = (
|
||||
'no-qpdf-object',
|
||||
'no-json-version',
|
||||
'no-pdf-version',
|
||||
'top-level-scalar',
|
||||
'bad-json-version1',
|
||||
'bad-json-version2',
|
||||
'bad-pdf-version1',
|
||||
'bad-pdf-version2',
|
||||
'top-level-array',
|
||||
'objects-not-dict',
|
||||
'bad-object-key',
|
||||
'object-not-dict',
|
||||
'stream-not-dict',
|
||||
'stream-dict-not-dict',
|
||||
'trailer-not-dict',
|
||||
'trailer-stream',
|
||||
);
|
||||
|
||||
$n_tests += scalar(@badfiles);
|
||||
|
||||
foreach my $f (@badfiles)
|
||||
{
|
||||
$td->runtest("bad: $f",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --create-from-json=qjson-$f.json a.pdf"},
|
||||
{$td->FILE => "qjson-$f.out", $td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
}
|
||||
|
||||
cleanup();
|
||||
$td->report($n_tests);
|
73
qpdf/qtest/qpdf/qjson-bad-json-version1.json
Normal file
73
qpdf/qtest/qpdf/qjson-bad-json-version1.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 16059,
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-bad-json-version1.out
Normal file
1
qpdf/qtest/qpdf/qjson-bad-json-version1.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-bad-json-version1.json: offset 98: only JSON version 2 is supported
|
73
qpdf/qtest/qpdf/qjson-bad-json-version2.json
Normal file
73
qpdf/qtest/qpdf/qjson-bad-json-version2.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": "potato",
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-bad-json-version2.out
Normal file
1
qpdf/qtest/qpdf/qjson-bad-json-version2.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-bad-json-version2.json: offset 98: only JSON version 2 is supported
|
75
qpdf/qtest/qpdf/qjson-bad-object-key.json
Normal file
75
qpdf/qtest/qpdf/qjson-bad-object-key.json
Normal file
@ -0,0 +1,75 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"potato": {
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-bad-object-key.out
Normal file
1
qpdf/qtest/qpdf/qjson-bad-object-key.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-bad-object-key.json: offset 181: object key should be "trailer" or "obj:n n R"
|
73
qpdf/qtest/qpdf/qjson-bad-pdf-version1.json
Normal file
73
qpdf/qtest/qpdf/qjson-bad-pdf-version1.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "potato",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-bad-pdf-version1.out
Normal file
1
qpdf/qtest/qpdf/qjson-bad-pdf-version1.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-bad-pdf-version1.json: offset 119: invalid PDF version (must be x.y)
|
73
qpdf/qtest/qpdf/qjson-bad-pdf-version2.json
Normal file
73
qpdf/qtest/qpdf/qjson-bad-pdf-version2.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": [],
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-bad-pdf-version2.out
Normal file
1
qpdf/qtest/qpdf/qjson-bad-pdf-version2.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-bad-pdf-version2.json: offset 119: invalid PDF version (must be x.y)
|
72
qpdf/qtest/qpdf/qjson-no-json-version.json
Normal file
72
qpdf/qtest/qpdf/qjson-no-json-version.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-no-json-version.out
Normal file
1
qpdf/qtest/qpdf/qjson-no-json-version.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-no-json-version.json: "qpdf.jsonversion" was not seen
|
72
qpdf/qtest/qpdf/qjson-no-pdf-version.json
Normal file
72
qpdf/qtest/qpdf/qjson-no-pdf-version.json
Normal file
@ -0,0 +1,72 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-no-pdf-version.out
Normal file
1
qpdf/qtest/qpdf/qjson-no-pdf-version.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-no-pdf-version.json: "qpdf.pdfversion" was not seen
|
3
qpdf/qtest/qpdf/qjson-no-qpdf-object.json
Normal file
3
qpdf/qtest/qpdf/qjson-no-qpdf-object.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"potato": "salad"
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-no-qpdf-object.out
Normal file
1
qpdf/qtest/qpdf/qjson-no-qpdf-object.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-no-qpdf-object.json: "qpdf" object was not seen
|
68
qpdf/qtest/qpdf/qjson-object-not-dict.json
Normal file
68
qpdf/qtest/qpdf/qjson-object-not-dict.json
Normal file
@ -0,0 +1,68 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"obj:1 0 R": "potato",
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-object-not-dict.out
Normal file
1
qpdf/qtest/qpdf/qjson-object-not-dict.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-object-not-dict.json: offset 184: "obj:1 0 R" must be a dictionary
|
7
qpdf/qtest/qpdf/qjson-objects-not-dict.json
Normal file
7
qpdf/qtest/qpdf/qjson-objects-not-dict.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.7",
|
||||
"objects": false
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-objects-not-dict.out
Normal file
1
qpdf/qtest/qpdf/qjson-objects-not-dict.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-objects-not-dict.json: offset 77: "objects" must be a dictionary
|
13
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json
Normal file
13
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.7",
|
||||
"objects": {
|
||||
"obj:1 0 R": {
|
||||
"stream": {
|
||||
"dict": "quack"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out
Normal file
1
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-stream-dict-not-dict.json: offset 137: "stream.dict" must be a dictionary
|
11
qpdf/qtest/qpdf/qjson-stream-not-dict.json
Normal file
11
qpdf/qtest/qpdf/qjson-stream-not-dict.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.7",
|
||||
"objects": {
|
||||
"obj:1 0 R": {
|
||||
"stream": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-stream-not-dict.out
Normal file
1
qpdf/qtest/qpdf/qjson-stream-not-dict.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-stream-not-dict.json: offset 118: "stream" must be a dictionary
|
1
qpdf/qtest/qpdf/qjson-top-level-array.json
Normal file
1
qpdf/qtest/qpdf/qjson-top-level-array.json
Normal file
@ -0,0 +1 @@
|
||||
["potato"]
|
1
qpdf/qtest/qpdf/qjson-top-level-array.out
Normal file
1
qpdf/qtest/qpdf/qjson-top-level-array.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-top-level-array.json: QPDF JSON must be a dictionary
|
1
qpdf/qtest/qpdf/qjson-top-level-scalar.json
Normal file
1
qpdf/qtest/qpdf/qjson-top-level-scalar.json
Normal file
@ -0,0 +1 @@
|
||||
"potato"
|
1
qpdf/qtest/qpdf/qjson-top-level-scalar.out
Normal file
1
qpdf/qtest/qpdf/qjson-top-level-scalar.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-top-level-scalar.json: QPDF JSON must be a dictionary
|
70
qpdf/qtest/qpdf/qjson-trailer-not-dict.json
Normal file
70
qpdf/qtest/qpdf/qjson-trailer-not-dict.json
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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": false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-trailer-not-dict.out
Normal file
1
qpdf/qtest/qpdf/qjson-trailer-not-dict.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-trailer-not-dict.json: offset 1326: "trailer.value" must be a dictionary
|
70
qpdf/qtest/qpdf/qjson-trailer-stream.json
Normal file
70
qpdf/qtest/qpdf/qjson-trailer-stream.json
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"version": 2,
|
||||
"parameters": {
|
||||
"decodelevel": "none"
|
||||
},
|
||||
"qpdf": {
|
||||
"jsonversion": 2,
|
||||
"pdfversion": "1.3",
|
||||
"maxobjectid": 6,
|
||||
"objects": {
|
||||
"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": {
|
||||
"stream": {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
qpdf/qtest/qpdf/qjson-trailer-stream.out
Normal file
1
qpdf/qtest/qpdf/qjson-trailer-stream.out
Normal file
@ -0,0 +1 @@
|
||||
qpdf: qjson-trailer-stream.json: offset 1327: the trailer may not be a stream
|
Loading…
Reference in New Issue
Block a user