2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-03 19:00:51 +00:00

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

View File

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

View File

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

View File

@ -8,6 +8,7 @@
#include <cstdio> #include <cstdio>
#include <ctype.h> #include <ctype.h>
#include <memory> #include <memory>
#include <sstream>
#include <qpdf/QUtil.hh> #include <qpdf/QUtil.hh>
#include <qpdf/QTC.hh> #include <qpdf/QTC.hh>
@ -15,6 +16,10 @@
#include <qpdf/QPDFArgParser.hh> #include <qpdf/QPDFArgParser.hh>
#include <qpdf/QPDFJob.hh> #include <qpdf/QPDFJob.hh>
#include <qpdf/QIntC.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 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 void
ArgParser::usage(std::string const& message) ArgParser::usage(std::string const& message)
{ {
@ -1534,3 +1564,93 @@ QPDFJob::initializeFromArgv(int argc, char* argv[], char const* progname_env)
ArgParser ap(qap, *this); ArgParser ap(qap, *this);
ap.parseOptions(); 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 argCopyright();
void argJsonHelp(); void argJsonHelp();
void argShowCrypto(); void argShowCrypto();
void argJobJsonHelp();
void argPositional(char*); void argPositional(char*);
void argAddAttachment(); void argAddAttachment();
void argAllowWeakCrypto(); void argAllowWeakCrypto();
@ -74,6 +75,7 @@ void argCopyEncryption(char *);
void argEncryptionFilePassword(char *); void argEncryptionFilePassword(char *);
void argForceVersion(char *); void argForceVersion(char *);
void argIiMinBytes(char *); void argIiMinBytes(char *);
void argJobJsonFile(char *);
void argJsonObject(char *); void argJsonObject(char *);
void argKeepFilesOpenThreshold(char *); void argKeepFilesOpenThreshold(char *);
void argLinearizePass1(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("--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: ap.addHelpTopic("exit-status", "meanings of qpdf's exit codes", R"(Meaning of exit codes:
0: no errors or warnings 0: no errors or warnings
@ -78,14 +83,14 @@ performed.
)"); )");
ap.addOptionHelp("--progress", "general", "show progress when writing", R"(Indicate progress when writing files. 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 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. encountered, qpdf still exits with exit status 3.
Use --warning-exit-0 with --no-warn to completely ignore Use --warning-exit-0 with --no-warn to completely ignore
warnings. 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 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 information, such as the page contents. Does not use the file's
name or attributes or the current time. 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 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. had in the original file.
)"); )");
}
static void add_help_3(QPDFArgParser& ap)
{
ap.addOptionHelp("--compress-streams", "transformation", "compress uncompressed streams", R"(--compress-streams=[yn] ap.addOptionHelp("--compress-streams", "transformation", "compress uncompressed streams", R"(--compress-streams=[yn]
Setting --compress-streams=n prevents qpdf from compressing Setting --compress-streams=n prevents qpdf from compressing
uncompressed streams. This can be useful if you are leaving some uncompressed streams. This can be useful if you are leaving some
streams uncompressed intentionally. streams uncompressed intentionally.
)"); )");
}
static void add_help_3(QPDFArgParser& ap)
{
ap.addOptionHelp("--decode-level", "transformation", "control which streams to uncompress", R"(--decode-level=parameter ap.addOptionHelp("--decode-level", "transformation", "control which streams to uncompress", R"(--decode-level=parameter
When uncompressing streams, control which types of compression 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. Run qpdf --help=page-selection for details.
)"); )");
}
static void add_help_4(QPDFArgParser& ap)
{
ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate=n ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate=n
Collate rather than concatenate pages specified with --pages. Collate rather than concatenate pages specified with --pages.
With a numeric parameter, collate in groups of n. The default With a numeric parameter, collate in groups of n. The default
is 1. Run qpdf --help=page-selection for additional details. 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] 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 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 Enable/disable text/graphic extraction for purposes other than
accessibility. accessibility.
)"); )");
}
static void add_help_5(QPDFArgParser& ap)
{
ap.addOptionHelp("--form", "encryption", "restrict form filling", R"(--form=[yn] ap.addOptionHelp("--form", "encryption", "restrict form filling", R"(--form=[yn]
Enable/disable whether filling form fields is allowed even if Enable/disable whether filling form fields is allowed even if
modification of annotations is disabled. This option is not modification of annotations is disabled. This option is not
available with 40-bit encryption. available with 40-bit encryption.
)"); )");
}
static void add_help_5(QPDFArgParser& ap)
{
ap.addOptionHelp("--modify-other", "encryption", "restrict other modifications", R"(--modify-other=[yn] ap.addOptionHelp("--modify-other", "encryption", "restrict other modifications", R"(--modify-other=[yn]
Enable/disable modifications not controlled by --assemble, 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 Remove an embedded file using its key. Get the key with
--list-attachments. --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 -- 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 The --copy-attachments-from flag and its options may be repeated
to copy attachments from multiple files. Run to copy attachments from multiple files. Run
qpdf --help=copy-attachments for details. 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 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 format specification, which is "D:yyyymmddhhmmssz" where "z" is
either literally upper case "Z" for UTC or a timezone offset in 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 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. 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) 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 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 locations in the file) in a human-readable form. This is
especially useful for files with cross-reference streams, which 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 be shown in the "objects" key of the JSON output. Otherwise, all
objects will be shown. 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 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. 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("copyright", b(&ArgParser::argCopyright));
this->ap.addBare("json-help", b(&ArgParser::argJsonHelp)); this->ap.addBare("json-help", b(&ArgParser::argJsonHelp));
this->ap.addBare("show-crypto", b(&ArgParser::argShowCrypto)); this->ap.addBare("show-crypto", b(&ArgParser::argShowCrypto));
this->ap.addBare("job-json-help", b(&ArgParser::argJobJsonHelp));
this->ap.selectMainOptionTable(); this->ap.selectMainOptionTable();
this->ap.addPositional(p(&ArgParser::argPositional)); this->ap.addPositional(p(&ArgParser::argPositional));
this->ap.addBare("add-attachment", b(&ArgParser::argAddAttachment)); 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("encryption-file-password", p(&ArgParser::argEncryptionFilePassword), "password");
this->ap.addRequiredParameter("force-version", p(&ArgParser::argForceVersion), "version"); this->ap.addRequiredParameter("force-version", p(&ArgParser::argForceVersion), "version");
this->ap.addRequiredParameter("ii-min-bytes", p(&ArgParser::argIiMinBytes), "minimum"); 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("json-object", p(&ArgParser::argJsonObject), "trailer");
this->ap.addRequiredParameter("keep-files-open-threshold", p(&ArgParser::argKeepFilesOpenThreshold), "count"); this->ap.addRequiredParameter("keep-files-open-threshold", p(&ArgParser::argKeepFilesOpenThreshold), "count");
this->ap.addRequiredParameter("linearize-pass1", p(&ArgParser::argLinearizePass1), "filename"); 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:`{infilename}.~qpdf-orig`. If there are errors, the input
file is left untouched. 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:
Exit Status Exit Status
@ -3147,6 +3159,14 @@ Related Options
be shown in the "``objects``" key of the JSON output. Otherwise, all be shown in the "``objects``" key of the JSON output. Otherwise, all
objects will be shown. 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: .. _test-options:
Options for Testing or Debugging Options for Testing or Debugging