mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Add --create-from-json and --update-from-json arguments
Also add stubs for top-level QPDF methods (createFromJSON, updateFromJSON)
This commit is contained in:
parent
ed6130036c
commit
4fe2e06b47
@ -215,6 +215,14 @@ CODING RULES
|
||||
|
||||
HOW TO ADD A COMMAND-LINE ARGUMENT
|
||||
|
||||
Quick reminder:
|
||||
|
||||
* Add an entry to the top half of job.yml for the command-line
|
||||
argument
|
||||
* Add an entry to the bottom half of job.yml for the job JSON field
|
||||
* Add documentation for the new option to cli.rst
|
||||
* Implement the QPDFJob::Config method in QPDFJob_config.cc.
|
||||
|
||||
QPDFJob is documented in three places:
|
||||
|
||||
* This section provides a quick reminder for how to add a command-line
|
||||
|
@ -110,6 +110,28 @@ class QPDF
|
||||
void
|
||||
processInputSource(std::shared_ptr<InputSource>, char const* password = 0);
|
||||
|
||||
// Create a PDF from an input source that contains JSON as written
|
||||
// by qpdf --json (version 2 or higher). The JSON must be a
|
||||
// complete representation of a PDF. See "QPDF JSON Format" in the
|
||||
// manual for details.
|
||||
QPDF_DLL
|
||||
void
|
||||
createFromJSON(std::string const& json_file);
|
||||
QPDF_DLL
|
||||
void
|
||||
createFromJSON(std::shared_ptr<InputSource>);
|
||||
|
||||
// Update a PDF from an input source that contains JSON in the
|
||||
// same format as is written by qpdf --json (version 2 or higher).
|
||||
// Objects in the PDF and not in the JSON are not modified. See
|
||||
// "QPDF JSON Format" in the manual for details.
|
||||
QPDF_DLL
|
||||
void
|
||||
updateFromJSON(std::string const& json_file);
|
||||
QPDF_DLL
|
||||
void
|
||||
updateFromJSON(std::shared_ptr<InputSource>);
|
||||
|
||||
// Close or otherwise release the input source. Once this has been
|
||||
// called, no other methods of qpdf can be called safely except
|
||||
// for getWarnings and anyWarnings(). After this has been called,
|
||||
|
@ -323,6 +323,8 @@ class QPDFJob
|
||||
Config* outputFile(std::string const& filename);
|
||||
QPDF_DLL
|
||||
Config* replaceInput();
|
||||
QPDF_DLL
|
||||
Config* createFromJson(std::string const& filename);
|
||||
|
||||
QPDF_DLL
|
||||
std::shared_ptr<CopyAttConfig> copyAttachmentsFrom();
|
||||
@ -674,6 +676,8 @@ class QPDFJob
|
||||
bool check_requires_password;
|
||||
std::shared_ptr<char> infilename;
|
||||
std::shared_ptr<char> outfilename;
|
||||
std::string create_from_json;
|
||||
std::string update_from_json;
|
||||
};
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
@ -68,6 +68,7 @@ QPDF_DLL Config* rotate(std::string const& parameter);
|
||||
QPDF_DLL Config* showAttachment(std::string const& parameter);
|
||||
QPDF_DLL Config* showObject(std::string const& parameter);
|
||||
QPDF_DLL Config* jsonStreamPrefix(std::string const& parameter);
|
||||
QPDF_DLL Config* updateFromJson(std::string const& parameter);
|
||||
QPDF_DLL Config* collate(std::string const& parameter);
|
||||
QPDF_DLL Config* collate();
|
||||
QPDF_DLL Config* splitPages(std::string const& parameter);
|
||||
|
18
job.sums
18
job.sums
@ -3,15 +3,15 @@ generate_auto_job 0514289f2deb3bf7c1a6e85ef7d99ad120321ef5a6fe49d76c5274c6a658d3
|
||||
include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
|
||||
include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
|
||||
include/qpdf/auto_job_c_enc.hh 28446f3c32153a52afa239ea40503e6cc8ac2c026813526a349e0cd4ae17ddd5
|
||||
include/qpdf/auto_job_c_main.hh 50214d1583d0384e70ce7c91d6bb92c58f8cc125490a680681cfffe6455a1dce
|
||||
include/qpdf/auto_job_c_main.hh 178a0c98c80d53036910ec67165dbc3902aa8da857de8a0df52911f005918c54
|
||||
include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c18911614fe8e568ec
|
||||
include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1
|
||||
job.yml c046a750e0cf6889b920484ab937bcb999be55273d77b263cb227b82006fbb36
|
||||
libqpdf/qpdf/auto_job_decl.hh 74df4d7fdbdf51ecd0d58ce1e9844bb5525b9adac5a45f7c9a787ecdda2868df
|
||||
libqpdf/qpdf/auto_job_help.hh e9b37d33bfcbf165bfba21b6778df3f356b904a961bfae68f9638b85142a87e8
|
||||
libqpdf/qpdf/auto_job_init.hh 423157a51fa470fb45d6e341cc3fc8f044b5344f06f86475b37302610c7d8afd
|
||||
libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297
|
||||
libqpdf/qpdf/auto_job_json_init.hh eaed8624a1a394c75a3e298e1c31015146211e240d710509eb627fc711a387a6
|
||||
libqpdf/qpdf/auto_job_schema.hh a9971c82c9821a5ec620ccc003bcb3383c054e45658b50fa559b5855e694ed1a
|
||||
job.yml a95b2446066293f409b36032a0ee411dbe570a7a94f5fd295048d009215f993f
|
||||
libqpdf/qpdf/auto_job_decl.hh 833bde9c1f8fc17b914f16498e26d9d1315361645b4ac5c50c1f830a76618ca7
|
||||
libqpdf/qpdf/auto_job_help.hh 38bf89067ca7dc244e4e697c598ba0ba8a827600a78b9195fc69f0ac1663f3a2
|
||||
libqpdf/qpdf/auto_job_init.hh f0ffab312430b232a7288b8443382ed859021e6ad6ed2c8c9a4dbbd2b33e2aa7
|
||||
libqpdf/qpdf/auto_job_json_decl.hh 81d09d4b82b2e042a64246ed1d7a187bdc83b671b45e7b8ee60ad37c0c11e9a7
|
||||
libqpdf/qpdf/auto_job_json_init.hh 2fcdae08365abe351d2dfb6a823e2b3af27a6510632de23cabef6cefa5dfb199
|
||||
libqpdf/qpdf/auto_job_schema.hh 1a80be3b8d97e9b5a55b8aa45a4b312668b1687eab6f038c4ee5f4662ab71997
|
||||
manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
|
||||
manual/cli.rst f1bbf59ce4fdb5a6d29fc2470788eee321423dd946984fc2e6f3a904fe5137c1
|
||||
manual/cli.rst 4550dd1b459721d8ef9affa7c9c07f351a06379498ec1291f702f1a5994b6d84
|
||||
|
5
job.yml
5
job.yml
@ -86,6 +86,7 @@ options:
|
||||
- underlay
|
||||
- empty
|
||||
- replace-input
|
||||
- create-from-json
|
||||
positional: true
|
||||
bare:
|
||||
- add-attachment
|
||||
@ -163,6 +164,8 @@ options:
|
||||
show-attachment: attachment
|
||||
show-object: trailer
|
||||
json-stream-prefix: stream-file-prefix
|
||||
create-from-json: qpdf-json file
|
||||
update-from-json: qpdf-json file
|
||||
required_choices:
|
||||
compress-streams: yn
|
||||
decode-level: decode_level
|
||||
@ -278,6 +281,7 @@ json:
|
||||
main.password:
|
||||
password-file:
|
||||
empty:
|
||||
create-from-json:
|
||||
# output
|
||||
_outputFile: "output filename"
|
||||
replace-input:
|
||||
@ -360,6 +364,7 @@ json:
|
||||
json-stream-prefix:
|
||||
to-json:
|
||||
# other options
|
||||
update-from-json:
|
||||
allow-weak-crypto:
|
||||
keep-files-open:
|
||||
keep-files-open-threshold:
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -100,6 +100,13 @@ ArgParser::argReplaceInput()
|
||||
this->gave_output = true;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argCreateFromJson(std::string const& arg)
|
||||
{
|
||||
c_main->createFromJson(arg);
|
||||
this->gave_input = true;
|
||||
}
|
||||
|
||||
void
|
||||
ArgParser::argVersion()
|
||||
{
|
||||
|
@ -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"
|
||||
@ -293,6 +295,23 @@ QPDFJob::Config::toJson()
|
||||
return this;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -250,6 +250,12 @@ Handlers::setupEmpty()
|
||||
addBare([this]() { c_main->emptyInput(); });
|
||||
}
|
||||
|
||||
void
|
||||
Handlers::setupCreateFromJson()
|
||||
{
|
||||
addParameter([this](char const* p) { c_main->createFromJson(p); });
|
||||
}
|
||||
|
||||
void
|
||||
Handlers::setupOutputFile()
|
||||
{
|
||||
|
27
libqpdf/QPDF_json.cc
Normal file
27
libqpdf/QPDF_json.cc
Normal file
@ -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
|
||||
}
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -8,6 +8,7 @@
|
||||
void setupInputFile();
|
||||
void setupPassword();
|
||||
void setupEmpty();
|
||||
void setupCreateFromJson();
|
||||
void setupOutputFile();
|
||||
void setupReplaceInput();
|
||||
void beginEncrypt(JSON);
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -3270,6 +3270,31 @@ Related Options
|
||||
:samp:`-{nnn}` to create the name of the file that will contain the
|
||||
data for the stream stream in object :samp:`{nnn}`.
|
||||
|
||||
.. qpdf:option:: --create-from-json=qpdf-json-file
|
||||
|
||||
.. help: create PDF from qpdf JSON
|
||||
|
||||
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.
|
||||
|
||||
This option creates a PDF file from the previous output of ``qpdf
|
||||
--json`` that includes stream data and information about all
|
||||
objects. For information about converting between PDF and JSON,
|
||||
please see :ref:`qpdf-json`.
|
||||
|
||||
.. qpdf:option:: --update-from-json=qpdf-json-file
|
||||
|
||||
.. help: update a PDF from qpdf JSON
|
||||
|
||||
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.
|
||||
|
||||
This option updates a PDF file from a qpdf JSON file. For a
|
||||
information about how to use this option, please see
|
||||
:ref:`qpdf-json`.
|
||||
|
||||
.. _test-options:
|
||||
|
||||
Options for Testing or Debugging
|
||||
|
@ -18,6 +18,13 @@ files programmatically from the command-line in languages that can't
|
||||
call or link with the qpdf library directly. Note that stream data can
|
||||
be extracted from PDF files using other qpdf command-line options.
|
||||
|
||||
.. _qpdf-json:
|
||||
|
||||
QPDF JSON Format
|
||||
----------------
|
||||
|
||||
QXXXQ Write this.
|
||||
|
||||
.. _json-guarantees:
|
||||
|
||||
JSON Guarantees
|
||||
|
Loading…
Reference in New Issue
Block a user