summaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-07-31 02:53:30 +0200
committerJay Berkenbilt <ejb@ql.org>2022-07-31 21:17:01 +0200
commit69820847af93cce0e400638999fee4d2cbb68db6 (patch)
tree2ade9466ffec2d57c381096e9bcdabd083d258a8 /libqpdf
parentd01c4f8819ea93797784c19ecdd623eb41f2a8b4 (diff)
downloadqpdf-69820847af93cce0e400638999fee4d2cbb68db6.tar.zst
Change the output of --json to use "qpdf" instead of "objects"
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/QPDFJob.cc80
-rw-r--r--libqpdf/QPDFJob_config.cc7
-rw-r--r--libqpdf/QPDF_json.cc3
-rw-r--r--libqpdf/qpdf/auto_job_init.hh2
-rw-r--r--libqpdf/qpdf/auto_job_json_init.hh2
5 files changed, 66 insertions, 28 deletions
diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc
index e09c0d74..e5914ddd 100644
--- a/libqpdf/QPDFJob.cc
+++ b/libqpdf/QPDFJob.cc
@@ -417,7 +417,7 @@ QPDFJob::Members::Members() :
check_is_encrypted(false),
check_requires_password(false),
json_input(false),
- json_output(0)
+ json_output(false)
{
}
@@ -728,8 +728,15 @@ QPDFJob::checkConfiguration()
" overwrite the input file");
}
- if (m->json_keys.count("objectinfo")) {
- usage("json key \"objectinfo\" is only valid for json version 1");
+ if (m->json_version == 1) {
+ if (m->json_keys.count("qpdf")) {
+ usage("json key \"qpdf\" is only valid for json version > 1");
+ }
+ } else {
+ if (m->json_keys.count("objectinfo") || m->json_keys.count("objects")) {
+ usage("json keys \"objects\" and \"objectinfo\" are only valid for"
+ " json version 1");
+ }
}
}
@@ -1568,12 +1575,12 @@ QPDFJob::json_schema(int json_version, std::set<std::string>* keys)
// The list of selectable top-level keys id duplicated in the
// following places: job.yml, QPDFJob::json_schema, and
// QPDFJob::doJSON.
- if (all_keys || keys->count("objects")) {
- schema.addDictionaryMember("objects", JSON::parse(R"({
+ if (json_version == 1) {
+ if (all_keys || keys->count("objects")) {
+ schema.addDictionaryMember("objects", JSON::parse(R"({
"<n n R|trailer>": "json representation of object"
})"));
- }
- if (json_version == 1) {
+ }
if (all_keys || keys->count("objectinfo")) {
JSON objectinfo =
schema.addDictionaryMember("objectinfo", JSON::parse(R"({
@@ -1586,6 +1593,19 @@ QPDFJob::json_schema(int json_version, std::set<std::string>* keys)
}
})"));
}
+ } else {
+ if (all_keys || keys->count("qpdf")) {
+ schema.addDictionaryMember("qpdf", JSON::parse(R"([{
+ "jsonversion": "numeric JSON version",
+ "pdfversion": "PDF version as x.y",
+ "pushedinheritedpageresources": "whether inherited attributes were pushed to the page level",
+ "calledgetallpages": "whether getAllPages was called",
+ "maxobjectid": "highest object ID in output, ignored on input"
+},
+{
+ "<obj:n n R|trailer>": "json representation of object"
+}])"));
+ }
}
if (all_keys || keys->count("pages")) {
JSON page = schema.addDictionaryMember("pages", JSON::parse(R"([
@@ -1812,9 +1832,14 @@ QPDFJob::doJSON(QPDF& pdf, Pipeline* p)
// We do objects last so their information is consistent with
// repairing the page tree. To see the original file with any page
// tree problems and the page tree not flattened, select
- // objects/objectinfo without other keys.
- if (all_keys || m->json_keys.count("objects")) {
- doJSONObjects(p, first, pdf);
+ // qpdf/objects/objectinfo without other keys.
+ if (all_keys || m->json_keys.count("objects") ||
+ m->json_keys.count("qpdf")) {
+ if (this->m->json_version == 1) {
+ doJSONObjects(p, first, pdf);
+ } else {
+ writeJSON(p, pdf, false, first);
+ }
}
if (this->m->json_version == 1) {
// "objectinfo" is not needed for version >1 since you can
@@ -2274,7 +2299,8 @@ QPDFJob::addAttachments(QPDF& pdf)
}
message = pdf.getFilename() +
" already has attachments with the following keys: " + message +
- "; use --replace to replace or --key to specify a different key";
+ "; use --replace to replace or --key to specify a different "
+ "key";
throw std::runtime_error(message);
}
}
@@ -2925,10 +2951,12 @@ QPDFJob::maybeFixWritePassword(int R, std::string& password)
<< this->m->message_prefix << ": WARNING: "
<< "supplied password looks like a Unicode"
<< " password with characters not allowed in"
- << " passwords for 40-bit and 128-bit encryption;"
+ << " passwords for 40-bit and 128-bit "
+ "encryption;"
<< " most readers will not be able to open this"
<< " file with the supplied password."
- << " (Use --password-mode=bytes to suppress this"
+ << " (Use --password-mode=bytes to suppress "
+ "this"
<< " warning and use the password anyway.)\n";
}
} else if ((R >= 5) && (!is_valid_utf8)) {
@@ -2978,13 +3006,15 @@ QPDFJob::setEncryptionOptions(QPDF& pdf, QPDFWriter& w)
QTC::TC("qpdf", "QPDFJob weak crypto error");
*this->m->log->getError()
<< this->m->message_prefix
- << ": refusing to write a file with RC4, a weak cryptographic "
+ << ": refusing to write a file with RC4, a weak "
+ "cryptographic "
"algorithm\n"
<< "Please use 256-bit keys for better security.\n"
<< "Pass --allow-weak-crypto to enable writing insecure "
"files.\n"
<< "See also "
- "https://qpdf.readthedocs.io/en/stable/weak-crypto.html\n";
+ "https://qpdf.readthedocs.io/en/stable/"
+ "weak-crypto.html\n";
throw std::runtime_error(
"refusing to write a file with weak crypto");
}
@@ -3293,7 +3323,8 @@ QPDFJob::writeOutfile(QPDF& pdf)
m->outfilename = nullptr;
}
if (this->m->json_output) {
- writeJSON(pdf);
+ bool unused = true;
+ writeJSON(nullptr, pdf, true, unused);
} else {
// QPDFWriter must have block scope so the output file will be
// closed after write() finishes.
@@ -3347,7 +3378,7 @@ QPDFJob::writeOutfile(QPDF& pdf)
}
void
-QPDFJob::writeJSON(QPDF& pdf)
+QPDFJob::writeJSON(Pipeline* p, QPDF& pdf, bool complete, bool& first_key)
{
// File pipeline must have block scope so it will be closed
// after write.
@@ -3369,7 +3400,12 @@ QPDFJob::writeJSON(QPDF& pdf)
"name is unknown");
} else {
QTC::TC("qpdf", "QPDFJob write json to stdout");
- fp = this->m->log->getInfo();
+ if (p == nullptr) {
+ fp = this->m->log->getInfo();
+ }
+ }
+ if (p == nullptr) {
+ p = fp.get();
}
std::set<std::string> json_objects;
if (this->m->json_objects.count("trailer")) {
@@ -3382,10 +3418,10 @@ QPDFJob::writeJSON(QPDF& pdf)
json_objects.insert(s.str());
}
pdf.writeJSON(
- this->m->json_output,
- fp.get(),
- true,
- true,
+ this->m->json_version,
+ p,
+ complete,
+ first_key,
this->m->decode_level,
this->m->json_stream_data,
file_prefix,
diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc
index 6a500b5c..9a2b3a84 100644
--- a/libqpdf/QPDFJob_config.cc
+++ b/libqpdf/QPDFJob_config.cc
@@ -296,12 +296,13 @@ QPDFJob::Config::jsonInput()
QPDFJob::Config*
QPDFJob::Config::jsonOutput(std::string const& parameter)
{
+ o.m->json_output = true;
if (parameter.empty() || (parameter == "latest")) {
- o.m->json_output = JSON::LATEST;
+ o.m->json_version = JSON::LATEST;
} else {
- o.m->json_output = QUtil::string_to_int(parameter.c_str());
+ o.m->json_version = QUtil::string_to_int(parameter.c_str());
}
- if ((o.m->json_output < 2) || (o.m->json_output > JSON::LATEST)) {
+ if ((o.m->json_version < 2) || (o.m->json_version > JSON::LATEST)) {
usage(std::string("unsupported json output version ") + parameter);
}
if (!o.m->json_stream_data_set) {
diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc
index 9ecb1b31..f90096f5 100644
--- a/libqpdf/QPDF_json.cc
+++ b/libqpdf/QPDF_json.cc
@@ -802,7 +802,7 @@ QPDF::writeJSON(
int version,
Pipeline* p,
bool complete,
- bool first_key,
+ bool& first_key,
qpdf_stream_decode_level_e decode_level,
qpdf_json_stream_data_e json_stream_data,
std::string const& file_prefix,
@@ -892,4 +892,5 @@ QPDF::writeJSON(
*p << "\n";
p->finish();
}
+ first_key = false;
}
diff --git a/libqpdf/qpdf/auto_job_init.hh b/libqpdf/qpdf/auto_job_init.hh
index c76a0b6a..0c5302e1 100644
--- a/libqpdf/qpdf/auto_job_init.hh
+++ b/libqpdf/qpdf/auto_job_init.hh
@@ -19,7 +19,7 @@ static char const* decode_level_choices[] = {"none", "generalized", "specialized
static char const* object_streams_choices[] = {"disable", "preserve", "generate", 0};
static char const* remove_unref_choices[] = {"auto", "yes", "no", 0};
static char const* flatten_choices[] = {"all", "print", "screen", 0};
-static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "objectinfo", "objects", "outlines", "pagelabels", "pages", 0};
+static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "objectinfo", "objects", "outlines", "pagelabels", "pages", "qpdf", 0};
static char const* json_output_choices[] = {"2", "latest", 0};
static char const* json_stream_data_choices[] = {"none", "inline", "file", 0};
static char const* json_version_choices[] = {"1", "2", "latest", 0};
diff --git a/libqpdf/qpdf/auto_job_json_init.hh b/libqpdf/qpdf/auto_job_json_init.hh
index 168d5676..8f8fb987 100644
--- a/libqpdf/qpdf/auto_job_json_init.hh
+++ b/libqpdf/qpdf/auto_job_json_init.hh
@@ -12,7 +12,7 @@ static char const* decode_level_choices[] = {"none", "generalized", "specialized
static char const* object_streams_choices[] = {"disable", "preserve", "generate", 0};
static char const* remove_unref_choices[] = {"auto", "yes", "no", 0};
static char const* flatten_choices[] = {"all", "print", "screen", 0};
-static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "objectinfo", "objects", "outlines", "pagelabels", "pages", 0};
+static char const* json_key_choices[] = {"acroform", "attachments", "encrypt", "objectinfo", "objects", "outlines", "pagelabels", "pages", "qpdf", 0};
static char const* json_output_choices[] = {"2", "latest", 0};
static char const* json_stream_data_choices[] = {"none", "inline", "file", 0};
static char const* json_version_choices[] = {"1", "2", "latest", 0};