aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/CMakeLists.txt1
-rw-r--r--libqpdf/QPDFJob.cc13
-rw-r--r--libqpdf/QPDFJob_argv.cc7
-rw-r--r--libqpdf/QPDFJob_config.cc31
-rw-r--r--libqpdf/QPDFJob_json.cc6
-rw-r--r--libqpdf/QPDF_json.cc27
-rw-r--r--libqpdf/qpdf/auto_job_decl.hh1
-rw-r--r--libqpdf/qpdf/auto_job_help.hh18
-rw-r--r--libqpdf/qpdf/auto_job_init.hh2
-rw-r--r--libqpdf/qpdf/auto_job_json_decl.hh1
-rw-r--r--libqpdf/qpdf/auto_job_json_init.hh6
-rw-r--r--libqpdf/qpdf/auto_job_schema.hh2
12 files changed, 105 insertions, 10 deletions
diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt
index aa7b1fd0..1777bb08 100644
--- a/libqpdf/CMakeLists.txt
+++ b/libqpdf/CMakeLists.txt
@@ -97,6 +97,7 @@ set(libqpdf_SOURCES
QPDF_Stream.cc
QPDF_String.cc
QPDF_encryption.cc
+ QPDF_json.cc
QPDF_linearization.cc
QPDF_optimization.cc
QPDF_pages.cc
diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc
index 55bebdcb..41e57c58 100644
--- a/libqpdf/QPDFJob.cc
+++ b/libqpdf/QPDFJob.cc
@@ -553,6 +553,13 @@ QPDFJob::run()
if (m->check_is_encrypted || m->check_requires_password) {
return;
}
+
+ // If we are updating from JSON, this has to be done first before
+ // other options may cause transformations to the input.
+ if (!this->m->update_from_json.empty()) {
+ pdf.updateFromJSON(this->m->update_from_json);
+ }
+
bool other_warnings = false;
std::vector<std::shared_ptr<QPDF>> page_heap;
if (!m->page_specs.empty()) {
@@ -1937,7 +1944,11 @@ QPDFJob::doProcessOnce(
auto pdf = std::make_shared<QPDF>();
setQPDFOptions(*pdf);
if (empty) {
- pdf->emptyPDF();
+ if (!this->m->create_from_json.empty()) {
+ pdf->createFromJSON(this->m->create_from_json);
+ } else {
+ pdf->emptyPDF();
+ }
} else {
fn(pdf.get(), password);
}
diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc
index a6fb5df7..3058d166 100644
--- a/libqpdf/QPDFJob_argv.cc
+++ b/libqpdf/QPDFJob_argv.cc
@@ -101,6 +101,13 @@ ArgParser::argReplaceInput()
}
void
+ArgParser::argCreateFromJson(std::string const& arg)
+{
+ c_main->createFromJson(arg);
+ this->gave_input = true;
+}
+
+void
ArgParser::argVersion()
{
auto whoami = this->ap.getProgname();
diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc
index f69a8137..1aa680e8 100644
--- a/libqpdf/QPDFJob_config.cc
+++ b/libqpdf/QPDFJob_config.cc
@@ -25,12 +25,14 @@ QPDFJob::Config::emptyInput()
{
if (o.m->infilename == 0) {
// Various places in QPDFJob.cc know that the empty string for
- // infile means empty. This means that passing "" as the
- // argument to inputFile, or equivalently using "" as a
- // positional command-line argument would be the same as
- // --empty. This probably isn't worth blocking or coding
- // around, but it would be better if we had a tighter way of
- // knowing that the input file is empty.
+ // infile means empty. We set it to something other than a
+ // null pointer as an indication that some input source has
+ // been specified. The --create-from-json option also sets
+ // infilename to empty. This approach means that passing "" as
+ // the argument to inputFile in job JSON, or equivalently
+ // using "" as a positional command-line argument would be the
+ // same as --empty. This probably isn't worth blocking or
+ // coding around.
o.m->infilename = QUtil::make_shared_cstr("");
} else {
usage("empty input can't be used"
@@ -294,6 +296,23 @@ QPDFJob::Config::toJson()
}
QPDFJob::Config*
+QPDFJob::Config::createFromJson(std::string const& parameter)
+{
+ // See comments in emptyInput() about setting infilename to the
+ // empty string.
+ o.m->infilename = QUtil::make_shared_cstr("");
+ o.m->create_from_json = parameter;
+ return this;
+}
+
+QPDFJob::Config*
+QPDFJob::Config::updateFromJson(std::string const& parameter)
+{
+ o.m->update_from_json = parameter;
+ return this;
+}
+
+QPDFJob::Config*
QPDFJob::Config::testJsonSchema()
{
o.m->test_json_schema = true;
diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc
index fcdeb666..9538153a 100644
--- a/libqpdf/QPDFJob_json.cc
+++ b/libqpdf/QPDFJob_json.cc
@@ -251,6 +251,12 @@ Handlers::setupEmpty()
}
void
+Handlers::setupCreateFromJson()
+{
+ addParameter([this](char const* p) { c_main->createFromJson(p); });
+}
+
+void
Handlers::setupOutputFile()
{
addParameter([this](char const* p) { c_main->outputFile(p); });
diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc
new file mode 100644
index 00000000..908615b6
--- /dev/null
+++ b/libqpdf/QPDF_json.cc
@@ -0,0 +1,27 @@
+#include <qpdf/QPDF.hh>
+
+#include <qpdf/FileInputSource.hh>
+
+void
+QPDF::createFromJSON(std::string const& json_file)
+{
+ createFromJSON(std::make_shared<FileInputSource>(json_file.c_str()));
+}
+
+void
+QPDF::createFromJSON(std::shared_ptr<InputSource>)
+{
+ // QXXXQ
+}
+
+void
+QPDF::updateFromJSON(std::string const& json_file)
+{
+ updateFromJSON(std::make_shared<FileInputSource>(json_file.c_str()));
+}
+
+void
+QPDF::updateFromJSON(std::shared_ptr<InputSource>)
+{
+ // QXXXQ
+}
diff --git a/libqpdf/qpdf/auto_job_decl.hh b/libqpdf/qpdf/auto_job_decl.hh
index 02f0ca91..8c656986 100644
--- a/libqpdf/qpdf/auto_job_decl.hh
+++ b/libqpdf/qpdf/auto_job_decl.hh
@@ -28,6 +28,7 @@ void argOverlay();
void argPages();
void argReplaceInput();
void argUnderlay();
+void argCreateFromJson(std::string const&);
void argPagesPositional(std::string const&);
void argPagesPassword(std::string const&);
void argEndPages();
diff --git a/libqpdf/qpdf/auto_job_help.hh b/libqpdf/qpdf/auto_job_help.hh
index d04f48a6..e17412d0 100644
--- a/libqpdf/qpdf/auto_job_help.hh
+++ b/libqpdf/qpdf/auto_job_help.hh
@@ -836,6 +836,21 @@ name as the prefix for stream data files. Whatever is given here
will be appended with -nnn to create the name of the file that
will contain the data for the stream stream in object nnn.
)");
+ap.addOptionHelp("--create-from-json", "json", "create PDF from qpdf JSON", R"(--create-from-json=qpdf-json-file
+
+Create a PDF file from the prior output of qpdf --json. See the
+"QPDF JSON Format" section of the manual for information about
+how to use this option.
+)");
+ap.addOptionHelp("--update-from-json", "json", "update a PDF from qpdf JSON", R"(--update-from-json=qpdf-json-file
+
+Update a PDF file from a JSON file. Please see the "QPDF JSON
+Format" section of the manual for information about how to use
+this option.
+)");
+}
+static void add_help_8(QPDFArgParser& ap)
+{
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.
)");
@@ -843,9 +858,6 @@ ap.addOptionHelp("--static-id", "testing", "use a fixed document ID", R"(Use a f
testing only. Never use it for production files. See also
qpdf --help=--deterministic-id.
)");
-}
-static void add_help_8(QPDFArgParser& ap)
-{
ap.addOptionHelp("--static-aes-iv", "testing", "use a fixed AES vector", R"(Use a static initialization vector for AES-CBC. This is intended
for testing only so that output files can be reproducible. Never
use it for production files. This option is not secure since it
diff --git a/libqpdf/qpdf/auto_job_init.hh b/libqpdf/qpdf/auto_job_init.hh
index f3ec1db6..9446811f 100644
--- a/libqpdf/qpdf/auto_job_init.hh
+++ b/libqpdf/qpdf/auto_job_init.hh
@@ -104,6 +104,8 @@ this->ap.addRequiredParameter("rotate", [this](std::string const& x){c_main->rot
this->ap.addRequiredParameter("show-attachment", [this](std::string const& x){c_main->showAttachment(x);}, "attachment");
this->ap.addRequiredParameter("show-object", [this](std::string const& x){c_main->showObject(x);}, "trailer");
this->ap.addRequiredParameter("json-stream-prefix", [this](std::string const& x){c_main->jsonStreamPrefix(x);}, "stream-file-prefix");
+this->ap.addRequiredParameter("create-from-json", p(&ArgParser::argCreateFromJson), "qpdf-json file");
+this->ap.addRequiredParameter("update-from-json", [this](std::string const& x){c_main->updateFromJson(x);}, "qpdf-json file");
this->ap.addOptionalParameter("collate", [this](std::string const& x){c_main->collate(x);});
this->ap.addOptionalParameter("split-pages", [this](std::string const& x){c_main->splitPages(x);});
this->ap.addChoices("compress-streams", [this](std::string const& x){c_main->compressStreams(x);}, true, yn_choices);
diff --git a/libqpdf/qpdf/auto_job_json_decl.hh b/libqpdf/qpdf/auto_job_json_decl.hh
index f02dc657..8160ca5a 100644
--- a/libqpdf/qpdf/auto_job_json_decl.hh
+++ b/libqpdf/qpdf/auto_job_json_decl.hh
@@ -8,6 +8,7 @@
void setupInputFile();
void setupPassword();
void setupEmpty();
+void setupCreateFromJson();
void setupOutputFile();
void setupReplaceInput();
void beginEncrypt(JSON);
diff --git a/libqpdf/qpdf/auto_job_json_init.hh b/libqpdf/qpdf/auto_job_json_init.hh
index cb349efc..ee124d0d 100644
--- a/libqpdf/qpdf/auto_job_json_init.hh
+++ b/libqpdf/qpdf/auto_job_json_init.hh
@@ -30,6 +30,9 @@ popHandler(); // key: passwordFile
pushKey("empty");
setupEmpty();
popHandler(); // key: empty
+pushKey("createFromJson");
+setupCreateFromJson();
+popHandler(); // key: createFromJson
pushKey("outputFile");
setupOutputFile();
popHandler(); // key: outputFile
@@ -262,6 +265,9 @@ popHandler(); // key: jsonStreamPrefix
pushKey("toJson");
addBare([this]() { c_main->toJson(); });
popHandler(); // key: toJson
+pushKey("updateFromJson");
+addParameter([this](std::string const& p) { c_main->updateFromJson(p); });
+popHandler(); // key: updateFromJson
pushKey("allowWeakCrypto");
addBare([this]() { c_main->allowWeakCrypto(); });
popHandler(); // key: allowWeakCrypto
diff --git a/libqpdf/qpdf/auto_job_schema.hh b/libqpdf/qpdf/auto_job_schema.hh
index 666b7260..0b9e29a9 100644
--- a/libqpdf/qpdf/auto_job_schema.hh
+++ b/libqpdf/qpdf/auto_job_schema.hh
@@ -3,6 +3,7 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({
"password": "password for encrypted file",
"passwordFile": "read password from a file",
"empty": "use empty file as input",
+ "createFromJson": "create PDF from qpdf JSON",
"outputFile": "output filename",
"replaceInput": "overwrite input with output",
"qdf": "enable viewing PDF code in a text editor",
@@ -87,6 +88,7 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({
"jsonStreamData": "how to handle streams in json output",
"jsonStreamPrefix": "prefix for json stream data files",
"toJson": "serialize to JSON",
+ "updateFromJson": "update a PDF from qpdf JSON",
"allowWeakCrypto": "allow insecure cryptographic algorithms",
"keepFilesOpen": "manage keeping multiple files open",
"keepFilesOpenThreshold": "set threshold for keepFilesOpen",