Commit 1d099ab7439104759a421bc20c809e64fef29f03

Authored by Jay Berkenbilt
1 parent 1c8d5346

QPDFJob: placeholder for initializeFromJson

include/qpdf/QPDFJob.hh
... ... @@ -35,6 +35,7 @@
35 35 #include <map>
36 36 #include <iostream>
37 37 #include <functional>
  38 +#include <memory>
38 39  
39 40 class QPDFWriter;
40 41  
... ... @@ -67,6 +68,10 @@ class QPDFJob
67 68 void initializeFromArgv(int argc, char* argv[],
68 69 char const* progname_env = nullptr);
69 70  
  71 + // QXXXQ
  72 + QPDF_DLL
  73 + void initializeFromJson(std::string const& json);
  74 +
70 75 // Set name that is used to prefix verbose messages, progress
71 76 // messages, and other things that the library writes to output
72 77 // and error streams on the caller's behalf. Defaults to "qpdf".
... ...
job.sums
1 1 # Generated by generate_auto_job
2 2 generate_auto_job 0758b244fc4e2d3e440883072d2740bc4cdb26c5aa8de938f028afd7d83fad79
3   -job.yml 2856c2635d42f0a58717d3ffce3125816d8f98ff17245c4b7a0669d70cd68b84
4   -libqpdf/qpdf/auto_job_decl.hh 97395ecbe590b23ae04d6cce2080dbd0e998917ff5eeaa5c6aafa91041d3cd6a
5   -libqpdf/qpdf/auto_job_help.hh 2653faaf59415bec81c3a85d426239d52b609ac24faba34ec2d26f00710dd2c6
6   -libqpdf/qpdf/auto_job_init.hh 465bf46769559ceb77110d1b9d3293ba9b3595850b49848c31aeabd10aadb4ad
  3 +job.yml 78d3b655abe70c0baaa31e51b74931f97084632bca5961fdbae89d7a57f34a67
  4 +libqpdf/qpdf/auto_job_decl.hh 9fda0ebd93bce6e308a3f26181293ad7b0d88a3503d4955cbf8e1db9a884d8ee
  5 +libqpdf/qpdf/auto_job_help.hh 383eea80e2c185ef5295fc126246457a7ceeffea759fdb90bb2e6727532ea538
  6 +libqpdf/qpdf/auto_job_init.hh a16e89fc7be3ca200d47391d949628a92113533135758068b944b64d0d54793d
7 7 libqpdf/qpdf/auto_job_schema.hh c91a4e182e088797b70dda94af03ca32d360f3564890132da2a8bdc3c4432423
8 8 manual/_ext/qpdf.py 855fe12de5af7a10bb24be6ecc4d5dff4c84ac58cf388a13be6bbb394346a67d
9   -manual/cli.rst b136c7f33a538c580b081a7e802c27635aad2a4229efa0eb0736466116b7aa90
  9 +manual/cli.rst 68122ff8179c10df3fe6d577adde4973c346f7866ba9a511bab5a6e6f292a6f1
... ...
... ... @@ -58,6 +58,7 @@ options:
58 58 - copyright
59 59 - json-help
60 60 - show-crypto
  61 + - job-json-help
61 62 - table: main
62 63 positional: true
63 64 bare:
... ... @@ -120,6 +121,7 @@ options:
120 121 encryption-file-password: password
121 122 force-version: version
122 123 ii-min-bytes: minimum
  124 + job-json-file: file
123 125 json-object: trailer
124 126 keep-files-open-threshold: count
125 127 linearize-pass1: filename
... ... @@ -219,6 +221,7 @@ options:
219 221 password: password
220 222 no-json:
221 223 - preserve-unreferenced-resources
  224 + - job-json-file
222 225 json:
223 226 # The structure of this section defines what the json input to
224 227 # QPDFJob looks like. If a key starts with underscore or has a value
... ...
libqpdf/QPDFJob_argv.cc
... ... @@ -8,6 +8,7 @@
8 8 #include <cstdio>
9 9 #include <ctype.h>
10 10 #include <memory>
  11 +#include <sstream>
11 12  
12 13 #include <qpdf/QUtil.hh>
13 14 #include <qpdf/QTC.hh>
... ... @@ -15,6 +16,10 @@
15 16 #include <qpdf/QPDFArgParser.hh>
16 17 #include <qpdf/QPDFJob.hh>
17 18 #include <qpdf/QIntC.hh>
  19 +#include <qpdf/JSONHandler.hh>
  20 +
  21 +#include <qpdf/auto_job_schema.hh>
  22 +static JSON JOB_SCHEMA = JSON::parse(JOB_SCHEMA_DATA);
18 23  
19 24 namespace
20 25 {
... ... @@ -1329,6 +1334,31 @@ ArgParser::argEndCopyAttachment()
1329 1334 }
1330 1335  
1331 1336 void
  1337 +ArgParser::argJobJsonFile(char* parameter)
  1338 +{
  1339 + PointerHolder<char> file_buf;
  1340 + size_t size;
  1341 + QUtil::read_file_into_memory(parameter, file_buf, size);
  1342 + try
  1343 + {
  1344 + o.initializeFromJson(std::string(file_buf.getPointer(), size));
  1345 + }
  1346 + catch (std::exception& e)
  1347 + {
  1348 + throw std::runtime_error(
  1349 + "error with job-json file " + std::string(parameter) + " " +
  1350 + e.what() + "\nRun " + this->ap.getProgname() +
  1351 + "--job-json-help for information on the file format.");
  1352 + }
  1353 +}
  1354 +
  1355 +void
  1356 +ArgParser::argJobJsonHelp()
  1357 +{
  1358 + std::cout << JOB_SCHEMA_DATA << std::endl;
  1359 +}
  1360 +
  1361 +void
1332 1362 ArgParser::usage(std::string const& message)
1333 1363 {
1334 1364 this->ap.usage(message);
... ... @@ -1534,3 +1564,93 @@ QPDFJob::initializeFromArgv(int argc, char* argv[], char const* progname_env)
1534 1564 ArgParser ap(qap, *this);
1535 1565 ap.parseOptions();
1536 1566 }
  1567 +
  1568 +void
  1569 +QPDFJob::initializeFromJson(std::string const& json)
  1570 +{
  1571 + std::list<std::string> errors;
  1572 + JSON j = JSON::parse(json);
  1573 + if (! j.checkSchema(JOB_SCHEMA, JSON::f_optional, errors))
  1574 + {
  1575 + std::ostringstream msg;
  1576 + msg << this->m->message_prefix
  1577 + << ": job json has errors:";
  1578 + for (auto const& error: errors)
  1579 + {
  1580 + msg << std::endl << " " << error;
  1581 + }
  1582 + throw std::runtime_error(msg.str());
  1583 + }
  1584 +
  1585 + JSONHandler jh;
  1586 + {
  1587 + jh.addDictHandlers(
  1588 + [](std::string const&){},
  1589 + [](std::string const&){});
  1590 +
  1591 + auto input = std::make_shared<JSONHandler>();
  1592 + auto input_file = std::make_shared<JSONHandler>();
  1593 + auto input_file_name = std::make_shared<JSONHandler>();
  1594 + auto output = std::make_shared<JSONHandler>();
  1595 + auto output_file = std::make_shared<JSONHandler>();
  1596 + auto output_file_name = std::make_shared<JSONHandler>();
  1597 + auto output_options = std::make_shared<JSONHandler>();
  1598 + auto output_options_qdf = std::make_shared<JSONHandler>();
  1599 +
  1600 + input->addDictHandlers(
  1601 + [](std::string const&){},
  1602 + [](std::string const&){});
  1603 + input_file->addDictHandlers(
  1604 + [](std::string const&){},
  1605 + [](std::string const&){});
  1606 + output->addDictHandlers(
  1607 + [](std::string const&){},
  1608 + [](std::string const&){});
  1609 + output_file->addDictHandlers(
  1610 + [](std::string const&){},
  1611 + [](std::string const&){});
  1612 + output_options->addDictHandlers(
  1613 + [](std::string const&){},
  1614 + [](std::string const&){});
  1615 +
  1616 + jh.addDictKeyHandler("input", input);
  1617 + input->addDictKeyHandler("file", input_file);
  1618 + input_file->addDictKeyHandler("name", input_file_name);
  1619 + jh.addDictKeyHandler("output", output);
  1620 + output->addDictKeyHandler("file", output_file);
  1621 + output_file->addDictKeyHandler("name", output_file_name);
  1622 + output->addDictKeyHandler("options", output_options);
  1623 + output_options->addDictKeyHandler("qdf", output_options_qdf);
  1624 +
  1625 + input_file_name->addStringHandler(
  1626 + [this](std::string const&, std::string const& v) {
  1627 + this->infilename = QUtil::make_shared_cstr(v);
  1628 + });
  1629 + output_file_name->addStringHandler(
  1630 + [this](std::string const&, std::string const& v) {
  1631 + this->outfilename = QUtil::make_shared_cstr(v);
  1632 + });
  1633 + output_options_qdf->addBoolHandler(
  1634 + [this](std::string const&, bool v) {
  1635 + this->qdf_mode = v;
  1636 + });
  1637 + }
  1638 +
  1639 + // {
  1640 + // "input": {
  1641 + // "file": {
  1642 + // "name": "/home/ejb/source/examples/pdf/minimal.pdf"
  1643 + // }
  1644 + // },
  1645 + // "output": {
  1646 + // "file": {
  1647 + // "name": "/tmp/a.pdf"
  1648 + // },
  1649 + // "options": {
  1650 + // "qdf": true
  1651 + // }
  1652 + // }
  1653 + // }
  1654 +
  1655 + jh.handle(".", j);
  1656 +}
... ...
libqpdf/qpdf/auto_job_decl.hh
... ... @@ -16,6 +16,7 @@ void argVersion();
16 16 void argCopyright();
17 17 void argJsonHelp();
18 18 void argShowCrypto();
  19 +void argJobJsonHelp();
19 20 void argPositional(char*);
20 21 void argAddAttachment();
21 22 void argAllowWeakCrypto();
... ... @@ -74,6 +75,7 @@ void argCopyEncryption(char *);
74 75 void argEncryptionFilePassword(char *);
75 76 void argForceVersion(char *);
76 77 void argIiMinBytes(char *);
  78 +void argJobJsonFile(char *);
77 79 void argJsonObject(char *);
78 80 void argKeepFilesOpenThreshold(char *);
79 81 void argLinearizePass1(char *);
... ...
libqpdf/qpdf/auto_job_help.hh
... ... @@ -27,6 +27,11 @@ with --pages.
27 27 )");
28 28 ap.addOptionHelp("--replace-input", "usage", "replace input with output", R"(Use in place of outfile to overwrite the input file with the output.
29 29 )");
  30 +ap.addOptionHelp("--job-json-file", "usage", "job JSON file", R"(--job-json-file=file
  31 +
  32 +Specify the name of a file whose contents are expected to
  33 +contain a QPDFJob json file.
  34 +)");
30 35 ap.addHelpTopic("exit-status", "meanings of qpdf's exit codes", R"(Meaning of exit codes:
31 36  
32 37 0: no errors or warnings
... ... @@ -78,14 +83,14 @@ performed.
78 83 )");
79 84 ap.addOptionHelp("--progress", "general", "show progress when writing", R"(Indicate progress when writing files.
80 85 )");
  86 +}
  87 +static void add_help_2(QPDFArgParser& ap)
  88 +{
81 89 ap.addOptionHelp("--no-warn", "general", "suppress printing warning messages", R"(Suppress printing warning messages. If warnings were
82 90 encountered, qpdf still exits with exit status 3.
83 91 Use --warning-exit-0 with --no-warn to completely ignore
84 92 warnings.
85 93 )");
86   -}
87   -static void add_help_2(QPDFArgParser& ap)
88   -{
89 94 ap.addOptionHelp("--deterministic-id", "general", "generate ID deterministically", R"(Generate a secure, random document ID only using static
90 95 information, such as the page contents. Does not use the file's
91 96 name or attributes or the current time.
... ... @@ -164,15 +169,15 @@ chapter about it in the manual.
164 169 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
165 170 had in the original file.
166 171 )");
  172 +}
  173 +static void add_help_3(QPDFArgParser& ap)
  174 +{
167 175 ap.addOptionHelp("--compress-streams", "transformation", "compress uncompressed streams", R"(--compress-streams=[yn]
168 176  
169 177 Setting --compress-streams=n prevents qpdf from compressing
170 178 uncompressed streams. This can be useful if you are leaving some
171 179 streams uncompressed intentionally.
172 180 )");
173   -}
174   -static void add_help_3(QPDFArgParser& ap)
175   -{
176 181 ap.addOptionHelp("--decode-level", "transformation", "control which streams to uncompress", R"(--decode-level=parameter
177 182  
178 183 When uncompressing streams, control which types of compression
... ... @@ -280,15 +285,15 @@ ap.addOptionHelp(&quot;--pages&quot;, &quot;modification&quot;, &quot;begin page selection&quot;, R&quot;(--pages f
280 285  
281 286 Run qpdf --help=page-selection for details.
282 287 )");
  288 +}
  289 +static void add_help_4(QPDFArgParser& ap)
  290 +{
283 291 ap.addOptionHelp("--collate", "modification", "collate with --pages", R"(--collate=n
284 292  
285 293 Collate rather than concatenate pages specified with --pages.
286 294 With a numeric parameter, collate in groups of n. The default
287 295 is 1. Run qpdf --help=page-selection for additional details.
288 296 )");
289   -}
290   -static void add_help_4(QPDFArgParser& ap)
291   -{
292 297 ap.addOptionHelp("--split-pages", "modification", "write pages to separate files", R"(--split-pages=[n]
293 298  
294 299 This option causes qpdf to create separate output files for each
... ... @@ -451,15 +456,15 @@ ap.addOptionHelp(&quot;--extract&quot;, &quot;encryption&quot;, &quot;restrict text/graphic extraction&quot;,
451 456 Enable/disable text/graphic extraction for purposes other than
452 457 accessibility.
453 458 )");
  459 +}
  460 +static void add_help_5(QPDFArgParser& ap)
  461 +{
454 462 ap.addOptionHelp("--form", "encryption", "restrict form filling", R"(--form=[yn]
455 463  
456 464 Enable/disable whether filling form fields is allowed even if
457 465 modification of annotations is disabled. This option is not
458 466 available with 40-bit encryption.
459 467 )");
460   -}
461   -static void add_help_5(QPDFArgParser& ap)
462   -{
463 468 ap.addOptionHelp("--modify-other", "encryption", "restrict other modifications", R"(--modify-other=[yn]
464 469  
465 470 Enable/disable modifications not controlled by --assemble,
... ... @@ -625,15 +630,15 @@ ap.addOptionHelp(&quot;--remove-attachment&quot;, &quot;attachments&quot;, &quot;remove an embedded file&quot;
625 630 Remove an embedded file using its key. Get the key with
626 631 --list-attachments.
627 632 )");
  633 +}
  634 +static void add_help_6(QPDFArgParser& ap)
  635 +{
628 636 ap.addOptionHelp("--copy-attachments-from", "attachments", "start copy attachment options", R"(--copy-attachments-from file options --
629 637  
630 638 The --copy-attachments-from flag and its options may be repeated
631 639 to copy attachments from multiple files. Run
632 640 qpdf --help=copy-attachments for details.
633 641 )");
634   -}
635   -static void add_help_6(QPDFArgParser& ap)
636   -{
637 642 ap.addHelpTopic("pdf-dates", "PDF date format", R"(When a date is required, the date should conform to the PDF date
638 643 format specification, which is "D:yyyymmddhhmmssz" where "z" is
639 644 either literally upper case "Z" for UTC or a timezone offset in
... ... @@ -738,11 +743,11 @@ encryption key to be displayed.
738 743 ap.addOptionHelp("--check-linearization", "inspection", "check linearization tables", R"(Check to see whether a file is linearized and, if so, whether
739 744 the linearization hint tables are correct.
740 745 )");
741   -ap.addOptionHelp("--show-linearization", "inspection", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
742   -)");
743 746 }
744 747 static void add_help_7(QPDFArgParser& ap)
745 748 {
  749 +ap.addOptionHelp("--show-linearization", "inspection", "show linearization hint tables", R"(Check and display all data in the linearization hint tables.
  750 +)");
746 751 ap.addOptionHelp("--show-xref", "inspection", "show cross reference data", R"(Show the contents of the cross-reference table or stream (object
747 752 locations in the file) in a human-readable form. This is
748 753 especially useful for files with cross-reference streams, which
... ... @@ -793,6 +798,8 @@ This option is repeatable. If given, only specified objects will
793 798 be shown in the "objects" key of the JSON output. Otherwise, all
794 799 objects will be shown.
795 800 )");
  801 +ap.addOptionHelp("--job-json-help", "json", "show format of job json", R"(Describe the format of the QPDFJob JSON input.
  802 +)");
796 803 ap.addHelpTopic("testing", "options for testing or debugging", R"(The options below are useful when writing automated test code that
797 804 includes files created by qpdf or when testing qpdf itself.
798 805 )");
... ...
libqpdf/qpdf/auto_job_init.hh
... ... @@ -26,6 +26,7 @@ this-&gt;ap.addBare(&quot;version&quot;, b(&amp;ArgParser::argVersion));
26 26 this->ap.addBare("copyright", b(&ArgParser::argCopyright));
27 27 this->ap.addBare("json-help", b(&ArgParser::argJsonHelp));
28 28 this->ap.addBare("show-crypto", b(&ArgParser::argShowCrypto));
  29 +this->ap.addBare("job-json-help", b(&ArgParser::argJobJsonHelp));
29 30 this->ap.selectMainOptionTable();
30 31 this->ap.addPositional(p(&ArgParser::argPositional));
31 32 this->ap.addBare("add-attachment", b(&ArgParser::argAddAttachment));
... ... @@ -85,6 +86,7 @@ this-&gt;ap.addRequiredParameter(&quot;copy-encryption&quot;, p(&amp;ArgParser::argCopyEncryption
85 86 this->ap.addRequiredParameter("encryption-file-password", p(&ArgParser::argEncryptionFilePassword), "password");
86 87 this->ap.addRequiredParameter("force-version", p(&ArgParser::argForceVersion), "version");
87 88 this->ap.addRequiredParameter("ii-min-bytes", p(&ArgParser::argIiMinBytes), "minimum");
  89 +this->ap.addRequiredParameter("job-json-file", p(&ArgParser::argJobJsonFile), "file");
88 90 this->ap.addRequiredParameter("json-object", p(&ArgParser::argJsonObject), "trailer");
89 91 this->ap.addRequiredParameter("keep-files-open-threshold", p(&ArgParser::argKeepFilesOpenThreshold), "count");
90 92 this->ap.addRequiredParameter("linearize-pass1", p(&ArgParser::argLinearizePass1), "filename");
... ...
manual/cli.rst
... ... @@ -157,6 +157,18 @@ Related Options
157 157 :file:`{infilename}.~qpdf-orig`. If there are errors, the input
158 158 file is left untouched.
159 159  
  160 +.. qpdf:option:: --job-json-file=file
  161 +
  162 + .. help: job JSON file
  163 +
  164 + Specify the name of a file whose contents are expected to
  165 + contain a QPDFJob json file.
  166 +
  167 + Specify the name of a file whose contents are expected to contain a
  168 + QPDFJob json file. QXXXQ ref. This file is read and treated as if
  169 + the equivalent command-line arguments were supplied. It can be
  170 + mixed freely with other options.
  171 +
160 172 .. _exit-status:
161 173  
162 174 Exit Status
... ... @@ -3147,6 +3159,14 @@ Related Options
3147 3159 be shown in the "``objects``" key of the JSON output. Otherwise, all
3148 3160 objects will be shown.
3149 3161  
  3162 +.. qpdf:option:: --job-json-help
  3163 +
  3164 + .. help: show format of job json
  3165 +
  3166 + Describe the format of the QPDFJob JSON input.
  3167 +
  3168 + Describe the format of the QPDFJob JSON input. QXXXQ doc ref.
  3169 +
3150 3170 .. _test-options:
3151 3171  
3152 3172 Options for Testing or Debugging
... ...