QPDFJob: placeholder for initializeFromJson

This commit is contained in:
Jay Berkenbilt 2022-01-22 16:29:13 -05:00
parent 1c8d53465f
commit 1d099ab743
8 changed files with 181 additions and 22 deletions

View File

@ -35,6 +35,7 @@
#include <map>
#include <iostream>
#include <functional>
#include <memory>
class QPDFWriter;
@ -67,6 +68,10 @@ class QPDFJob
void initializeFromArgv(int argc, char* argv[],
char const* progname_env = nullptr);
// QXXXQ
QPDF_DLL
void initializeFromJson(std::string const& json);
// Set name that is used to prefix verbose messages, progress
// messages, and other things that the library writes to output
// and error streams on the caller's behalf. Defaults to "qpdf".

View File

@ -1,9 +1,9 @@
# Generated by generate_auto_job
generate_auto_job 0758b244fc4e2d3e440883072d2740bc4cdb26c5aa8de938f028afd7d83fad79
job.yml 2856c2635d42f0a58717d3ffce3125816d8f98ff17245c4b7a0669d70cd68b84
libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a
libqpdf/qpdf/auto_job_help.hh 2653faaf59415bec81c3a85d426239d52b609ac24faba34ec2d26f00710dd2c6
libqpdf/qpdf/auto_job_init.hh 465bf46769559ceb77110d1b9d3293ba9b3595850b49848c31aeabd10aadb4ad
job.yml 78d3b655abe70c0baaa31e51b74931f97084632bca5961fdbae89d7a57f34a67
libqpdf/qpdf/auto_job_decl.hh 9fda0ebd93bce6e308a3f26181293ad7b0d88a3503d4955cbf8e1db9a884d8ee
libqpdf/qpdf/auto_job_help.hh 383eea80e2c185ef5295fc126246457a7ceeffea759fdb90bb2e6727532ea538
libqpdf/qpdf/auto_job_init.hh a16e89fc7be3ca200d47391d949628a92113533135758068b944b64d0d54793d
libqpdf/qpdf/auto_job_schema.hh c91a4e182e088797b70dda94af03ca32d360f3564890132da2a8bdc3c4432423
manual/_ext/qpdf.py 855fe12de5af7a10bb24be6ecc4d5dff4c84ac58cf388a13be6bbb394346a67d
manual/cli.rst b136c7f33a538c580b081a7e802c27635aad2a4229efa0eb0736466116b7aa90
manual/cli.rst 68122ff8179c10df3fe6d577adde4973c346f7866ba9a511bab5a6e6f292a6f1

View File

@ -58,6 +58,7 @@ options:
- copyright
- json-help
- show-crypto
- job-json-help
- table: main
positional: true
bare:
@ -120,6 +121,7 @@ options:
encryption-file-password: password
force-version: version
ii-min-bytes: minimum
job-json-file: file
json-object: trailer
keep-files-open-threshold: count
linearize-pass1: filename
@ -219,6 +221,7 @@ options:
password: password
no-json:
- preserve-unreferenced-resources
- job-json-file
json:
# The structure of this section defines what the json input to
# QPDFJob looks like. If a key starts with underscore or has a value

View File

@ -8,6 +8,7 @@
#include <cstdio>
#include <ctype.h>
#include <memory>
#include <sstream>
#include <qpdf/QUtil.hh>
#include <qpdf/QTC.hh>
@ -15,6 +16,10 @@
#include <qpdf/QPDFArgParser.hh>
#include <qpdf/QPDFJob.hh>
#include <qpdf/QIntC.hh>
#include <qpdf/JSONHandler.hh>
#include <qpdf/auto_job_schema.hh>
static JSON JOB_SCHEMA = JSON::parse(JOB_SCHEMA_DATA);
namespace
{
@ -1328,6 +1333,31 @@ ArgParser::argEndCopyAttachment()
}
}
void
ArgParser::argJobJsonFile(char* parameter)
{
PointerHolder<char> file_buf;
size_t size;
QUtil::read_file_into_memory(parameter, file_buf, size);
try
{
o.initializeFromJson(std::string(file_buf.getPointer(), size));
}
catch (std::exception& e)
{
throw std::runtime_error(
"error with job-json file " + std::string(parameter) + " " +
e.what() + "\nRun " + this->ap.getProgname() +
"--job-json-help for information on the file format.");
}
}
void
ArgParser::argJobJsonHelp()
{
std::cout << JOB_SCHEMA_DATA << std::endl;
}
void
ArgParser::usage(std::string const& message)
{
@ -1534,3 +1564,93 @@ QPDFJob::initializeFromArgv(int argc, char* argv[], char const* progname_env)
ArgParser ap(qap, *this);
ap.parseOptions();
}
void
QPDFJob::initializeFromJson(std::string const& json)
{
std::list<std::string> errors;
JSON j = JSON::parse(json);
if (! j.checkSchema(JOB_SCHEMA, JSON::f_optional, errors))
{
std::ostringstream msg;
msg << this->m->message_prefix
<< ": job json has errors:";
for (auto const& error: errors)
{
msg << std::endl << " " << error;
}
throw std::runtime_error(msg.str());
}
JSONHandler jh;
{
jh.addDictHandlers(
[](std::string const&){},
[](std::string const&){});
auto input = std::make_shared<JSONHandler>();
auto input_file = std::make_shared<JSONHandler>();
auto input_file_name = std::make_shared<JSONHandler>();
auto output = std::make_shared<JSONHandler>();
auto output_file = std::make_shared<JSONHandler>();
auto output_file_name = std::make_shared<JSONHandler>();
auto output_options = std::make_shared<JSONHandler>();
auto output_options_qdf = std::make_shared<JSONHandler>();
input->addDictHandlers(
[](std::string const&){},
[](std::string const&){});
input_file->addDictHandlers(
[](std::string const&){},
[](std::string const&){});
output->addDictHandlers(
[](std::string const&){},
[](std::string const&){});
output_file->addDictHandlers(
[](std::string const&){},
[](std::string const&){});
output_options->addDictHandlers(
[](std::string const&){},
[](std::string const&){});
jh.addDictKeyHandler("input", input);
input->addDictKeyHandler("file", input_file);
input_file->addDictKeyHandler("name", input_file_name);
jh.addDictKeyHandler("output", output);
output->addDictKeyHandler("file", output_file);
output_file->addDictKeyHandler("name", output_file_name);
output->addDictKeyHandler("options", output_options);
output_options->addDictKeyHandler("qdf", output_options_qdf);
input_file_name->addStringHandler(
[this](std::string const&, std::string const& v) {
this->infilename = QUtil::make_shared_cstr(v);
});
output_file_name->addStringHandler(
[this](std::string const&, std::string const& v) {
this->outfilename = QUtil::make_shared_cstr(v);
});
output_options_qdf->addBoolHandler(
[this](std::string const&, bool v) {
this->qdf_mode = v;
});
}
// {
// "input": {
// "file": {
// "name": "/home/ejb/source/examples/pdf/minimal.pdf"
// }
// },
// "output": {
// "file": {
// "name": "/tmp/a.pdf"
// },
// "options": {
// "qdf": true
// }
// }
// }
jh.handle(".", j);
}

View File

@ -16,6 +16,7 @@ void argVersion();
void argCopyright();
void argJsonHelp();
void argShowCrypto();
void argJobJsonHelp();
void argPositional(char*);
void argAddAttachment();
void argAllowWeakCrypto();
@ -74,6 +75,7 @@ void argCopyEncryption(char *);
void argEncryptionFilePassword(char *);
void argForceVersion(char *);
void argIiMinBytes(char *);
void argJobJsonFile(char *);
void argJsonObject(char *);
void argKeepFilesOpenThreshold(char *);
void argLinearizePass1(char *);

View File

@ -27,6 +27,11 @@ with --pages.
)");
ap.addOptionHelp("--replace-input", "usage", "replace input with output", R"(Use in place of outfile to overwrite the input file with the output.
)");
ap.addOptionHelp("--job-json-file", "usage", "job JSON file", R"(--job-json-file=file
Specify the name of a file whose contents are expected to
contain a QPDFJob json file.
)");
ap.addHelpTopic("exit-status", "meanings of qpdf's exit codes", R"(Meaning of exit codes:
0: no errors or warnings
@ -78,14 +83,14 @@ performed.
)");
ap.addOptionHelp("--progress", "general", "show progress when writing", R"(Indicate progress when writing files.
)");
}
static void add_help_2(QPDFArgParser& ap)
{
ap.addOptionHelp("--no-warn", "general", "suppress printing warning messages", R"(Suppress printing warning messages. If warnings were
encountered, qpdf still exits with exit status 3.
Use --warning-exit-0 with --no-warn to completely ignore
warnings.
)");
}
static void add_help_2(QPDFArgParser& ap)
{
ap.addOptionHelp("--deterministic-id", "general", "generate ID deterministically", R"(Generate a secure, random document ID only using static
information, such as the page contents. Does not use the file's
name or attributes or the current time.
@ -164,15 +169,15 @@ chapter about it in the manual.
ap.addOptionHelp("--no-original-object-ids", "transformation", "omit original object ID in qdf", R"(Omit comments in a QDF file indicating the object ID an object
had in the original file.
)");
}
static void add_help_3(QPDFArgParser& ap)
{
ap.addOptionHelp("--compress-streams", "transformation", "compress uncompressed streams", R"(--compress-streams=[yn]
Setting --compress-streams=n prevents qpdf from compressing
uncompressed streams. This can be useful if you are leaving some
streams uncompressed intentionally.
)");
}
static void add_help_3(QPDFArgParser& ap)
{
ap.addOptionHelp("--decode-level", "transformation", "control which streams to uncompress", R"(--decode-level=parameter
When uncompressing streams, control which types of compression
@ -280,15 +285,15 @@ ap.addOptionHelp("--pages", "modification", "begin page selection", R"(--pages f
Run qpdf --help=page-selection for details.
)");
}
static void add_help_4(QPDFArgParser& ap)
{
ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate=n
Collate rather than concatenate pages specified with --pages.
With a numeric parameter, collate in groups of n. The default
is 1. Run qpdf --help=page-selection for additional details.
)");
}
static void add_help_4(QPDFArgParser& ap)
{
ap.addOptionHelp("--split-pages", "modification", "write pages to separate files", R"(--split-pages=[n]
This option causes qpdf to create separate output files for each
@ -451,15 +456,15 @@ ap.addOptionHelp("--extract", "encryption", "restrict text/graphic extraction",
Enable/disable text/graphic extraction for purposes other than
accessibility.
)");
}
static void add_help_5(QPDFArgParser& ap)
{
ap.addOptionHelp("--form", "encryption", "restrict form filling", R"(--form=[yn]
Enable/disable whether filling form fields is allowed even if
modification of annotations is disabled. This option is not
available with 40-bit encryption.
)");
}
static void add_help_5(QPDFArgParser& ap)
{
ap.addOptionHelp("--modify-other", "encryption", "restrict other modifications", R"(--modify-other=[yn]
Enable/disable modifications not controlled by --assemble,
@ -625,15 +630,15 @@ ap.addOptionHelp("--remove-attachment", "attachments", "remove an embedded file"
Remove an embedded file using its key. Get the key with
--list-attachments.
)");
}
static void add_help_6(QPDFArgParser& ap)
{
ap.addOptionHelp("--copy-attachments-from", "attachments", "start copy attachment options", R"(--copy-attachments-from file options --
The --copy-attachments-from flag and its options may be repeated
to copy attachments from multiple files. Run
qpdf --help=copy-attachments for details.
)");
}
static void add_help_6(QPDFArgParser& ap)
{
ap.addHelpTopic("pdf-dates", "PDF date format", R"(When a date is required, the date should conform to the PDF date
format specification, which is "D:yyyymmddhhmmssz" where "z" is
either literally upper case "Z" for UTC or a timezone offset in
@ -738,11 +743,11 @@ encryption key to be displayed.
ap.addOptionHelp("--check-linearization", "inspection", "check linearization tables", R"(Check to see whether a file is linearized and, if so, whether
the linearization hint tables are correct.
)");
ap.addOptionHelp("--show-linearization", "inspection", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
)");
}
static void add_help_7(QPDFArgParser& ap)
{
ap.addOptionHelp("--show-linearization", "inspection", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
)");
ap.addOptionHelp("--show-xref", "inspection", "show cross reference data", R"(Show the contents of the cross-reference table or stream (object
locations in the file) in a human-readable form. This is
especially useful for files with cross-reference streams, which
@ -793,6 +798,8 @@ This option is repeatable. If given, only specified objects will
be shown in the "objects" key of the JSON output. Otherwise, all
objects will be shown.
)");
ap.addOptionHelp("--job-json-help", "json", "show format of job json", R"(Describe the format of the QPDFJob JSON input.
)");
ap.addHelpTopic("testing", "options for testing or debugging", R"(The options below are useful when writing automated test code that
includes files created by qpdf or when testing qpdf itself.
)");

View File

@ -26,6 +26,7 @@ this->ap.addBare("version", b(&ArgParser::argVersion));
this->ap.addBare("copyright", b(&ArgParser::argCopyright));
this->ap.addBare("json-help", b(&ArgParser::argJsonHelp));
this->ap.addBare("show-crypto", b(&ArgParser::argShowCrypto));
this->ap.addBare("job-json-help", b(&ArgParser::argJobJsonHelp));
this->ap.selectMainOptionTable();
this->ap.addPositional(p(&ArgParser::argPositional));
this->ap.addBare("add-attachment", b(&ArgParser::argAddAttachment));
@ -85,6 +86,7 @@ this->ap.addRequiredParameter("copy-encryption", p(&ArgParser::argCopyEncryption
this->ap.addRequiredParameter("encryption-file-password", p(&ArgParser::argEncryptionFilePassword), "password");
this->ap.addRequiredParameter("force-version", p(&ArgParser::argForceVersion), "version");
this->ap.addRequiredParameter("ii-min-bytes", p(&ArgParser::argIiMinBytes), "minimum");
this->ap.addRequiredParameter("job-json-file", p(&ArgParser::argJobJsonFile), "file");
this->ap.addRequiredParameter("json-object", p(&ArgParser::argJsonObject), "trailer");
this->ap.addRequiredParameter("keep-files-open-threshold", p(&ArgParser::argKeepFilesOpenThreshold), "count");
this->ap.addRequiredParameter("linearize-pass1", p(&ArgParser::argLinearizePass1), "filename");

View File

@ -157,6 +157,18 @@ Related Options
:file:`{infilename}.~qpdf-orig`. If there are errors, the input
file is left untouched.
.. qpdf:option:: --job-json-file=file
.. help: job JSON file
Specify the name of a file whose contents are expected to
contain a QPDFJob json file.
Specify the name of a file whose contents are expected to contain a
QPDFJob json file. QXXXQ ref. This file is read and treated as if
the equivalent command-line arguments were supplied. It can be
mixed freely with other options.
.. _exit-status:
Exit Status
@ -3147,6 +3159,14 @@ Related Options
be shown in the "``objects``" key of the JSON output. Otherwise, all
objects will be shown.
.. qpdf:option:: --job-json-help
.. help: show format of job json
Describe the format of the QPDFJob JSON input.
Describe the format of the QPDFJob JSON input. QXXXQ doc ref.
.. _test-options:
Options for Testing or Debugging