From 1d099ab7439104759a421bc20c809e64fef29f03 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 22 Jan 2022 16:29:13 -0500 Subject: QPDFJob: placeholder for initializeFromJson --- libqpdf/QPDFJob_argv.cc | 120 ++++++++++++++++++++++++++++++++++++++++++ libqpdf/qpdf/auto_job_decl.hh | 2 + libqpdf/qpdf/auto_job_help.hh | 41 +++++++++------ libqpdf/qpdf/auto_job_init.hh | 2 + 4 files changed, 148 insertions(+), 17 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc index 8da5e836..f4a4219a 100644 --- a/libqpdf/QPDFJob_argv.cc +++ b/libqpdf/QPDFJob_argv.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,10 @@ #include #include #include +#include + +#include +static JSON JOB_SCHEMA = JSON::parse(JOB_SCHEMA_DATA); namespace { @@ -1328,6 +1333,31 @@ ArgParser::argEndCopyAttachment() } } +void +ArgParser::argJobJsonFile(char* parameter) +{ + PointerHolder 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 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(); + auto input_file = std::make_shared(); + auto input_file_name = std::make_shared(); + auto output = std::make_shared(); + auto output_file = std::make_shared(); + auto output_file_name = std::make_shared(); + auto output_options = std::make_shared(); + auto output_options_qdf = std::make_shared(); + + 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); +} diff --git a/libqpdf/qpdf/auto_job_decl.hh b/libqpdf/qpdf/auto_job_decl.hh index 1f2b4263..6d5c8228 100644 --- a/libqpdf/qpdf/auto_job_decl.hh +++ b/libqpdf/qpdf/auto_job_decl.hh @@ -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 *); diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh index dd55fb0c..982509ee 100644 --- a/libqpdf/qpdf/auto_job_help.hh +++ b/libqpdf/qpdf/auto_job_help.hh @@ -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. )"); diff --git a/libqpdf/qpdf/auto_job_init.hh b/libqpdf/qpdf/auto_job_init.hh index 3d7cdd7b..f9de9f90 100644 --- a/libqpdf/qpdf/auto_job_init.hh +++ b/libqpdf/qpdf/auto_job_init.hh @@ -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"); -- cgit v1.2.3-54-g00ecf