QPDFJob_json: implement handlers except pages

This commit is contained in:
Jay Berkenbilt 2022-01-30 13:39:17 -05:00
parent e01bbccb40
commit b74e7989c3
6 changed files with 199 additions and 185 deletions

View File

@ -6,12 +6,12 @@ include/qpdf/auto_job_c_enc.hh 72e138c7b96ed5aacdce78c1dec04b1c20d361faec4f8faf5
include/qpdf/auto_job_c_main.hh 516adb23cc7e44e614e436880be870d0574e4ebbc706cd855a1360000eed31bb
include/qpdf/auto_job_c_pages.hh 931840b329a36ca0e41401190e04537b47f2867671a6643bfd8da74014202671
include/qpdf/auto_job_c_uo.hh 0585b7de459fa479d9e51a45fa92de0ff6dee748efc9ec1cedd0dde6cee1ad50
job.yml 7433861fa281197aa275d624a334aa324ec63839c5e56a24448ab64d0b75587c
job.yml 6389b89c25f0f07fa54bfc3d9f24f814aac5566ace43666f81476781db616ea1
libqpdf/qpdf/auto_job_decl.hh 9f79396ec459f191be4c5fe34cf88c265cf47355a1a945fa39169d1c94cf04f6
libqpdf/qpdf/auto_job_help.hh 23c79f1d2c02bda28f64aace17f69487205c797e7ae2234892cbbabab49d6d47
libqpdf/qpdf/auto_job_init.hh 8e9e31b6099a662497339b27f6e2d7f779f35011e88a834bee8811c33405a0fe
libqpdf/qpdf/auto_job_json_decl.hh d315f920a32d7a5a2272807e6813d463c3e1877a9d735e44e8417b5f1461b87a
libqpdf/qpdf/auto_job_json_init.hh 08e6ee8a509bc592e3aa6f7a1d3a6d18cdf4803e6220147855caf675e0a299ce
libqpdf/qpdf/auto_job_schema.hh 6ec5b9dd3b4709b49fb3b928c4d9cde8b35ad938a0945f81c9a3da6c3bf9a3c1
libqpdf/qpdf/auto_job_json_decl.hh 8a6e3b25e01969f1c8e2c9ec781f7f2e89b57e67e65d5dc7445ad9124b694b9a
libqpdf/qpdf/auto_job_json_init.hh 48888c602de4cc13040cff26569e162d6ebb5aec6ab959164d432cfe1058eb23
libqpdf/qpdf/auto_job_schema.hh 9e19fb0b8ddd6fe13da12f1f98c27f6d558fc4706a56a63697e529b3140a457c
manual/_ext/qpdf.py e9ac9d6c70642a3d29281ee5ad92ae2422dee8be9306fb8a0bc9dba0ed5e28f3
manual/cli.rst 79140e023faa0cb77afe0b1dc512dd120ee5617f4db82f842596e4f239f93882

28
job.yml
View File

@ -318,19 +318,6 @@ json:
Enc256.print:
allow-insecure:
force-R5:
_options:
allow-weak-crypto:
deterministic-id:
keep-files-open:
keep-files-open-threshold:
no-warn:
verbose:
warning-exit-0:
ignore-xref-streams:
password-is-hex-key:
password-mode:
suppress-password-recovery:
suppress-recovery:
_inspect:
check:
check-linearization:
@ -353,13 +340,24 @@ json:
- null
json-object:
- null
_transform:
_options:
allow-weak-crypto:
deterministic-id:
keep-files-open:
keep-files-open-threshold:
no-warn:
verbose:
warning-exit-0:
ignore-xref-streams:
password-is-hex-key:
password-mode:
suppress-password-recovery:
suppress-recovery:
coalesce-contents:
compression-level:
externalize-inline-images:
ii-min-bytes:
remove-unreferenced-resources:
_modify:
add-attachment:
- path: "attachment to add"
creationdate:

View File

@ -229,7 +229,9 @@ Handlers::setupInputFilename(std::string const& key)
void
Handlers::setupInputPassword(std::string const& key)
{
// QXXXQ
addParameter(key, [this](char const* p) {
c_main->password(p);
});
}
void
@ -281,21 +283,53 @@ Handlers::endOutputOptions()
}
void
Handlers::beginOutputOptionsEncrypt(JSON)
Handlers::beginOutputOptionsEncrypt(JSON j)
{
// QXXXQ
// if (this->keylen_seen == 0)
// {
// usage("exactly one of 40bit, 128bit, or 256bit must be given;"
// " an empty dictionary may be supplied for one of them"
// " to set the key length without imposing any restrictions");
// }
// This method is only called if the overall JSON structure
// matches the schema, so we already know that keys that are
// present have the right types.
int key_len = 0;
std::string user_password;
std::string owner_password;
bool user_password_seen = false;
bool owner_password_seen = false;
j.forEachDictItem([&](std::string const& key, JSON value){
if ((key == "40bit") || (key == "128bit") || (key == "256bit"))
{
if (key_len != 0)
{
usage("exactly one of 40bit, 128bit, or 256bit must be given");
}
key_len = QUtil::string_to_int(key.c_str());
}
else if (key == "userPassword")
{
user_password_seen = value.getString(user_password);
}
else if (key == "ownerPassword")
{
owner_password_seen = value.getString(owner_password);
}
});
if (key_len == 0)
{
usage("exactly one of 40bit, 128bit, or 256bit must be given;"
" an empty dictionary may be supplied for one of them"
" to set the key length without imposing any restrictions");
}
if (! (user_password_seen && owner_password_seen))
{
usage("the user and owner password are both required; use the empty"
" string for the user password if you don't want a password");
}
this->c_enc = c_main->encrypt(key_len, user_password, owner_password);
}
void
Handlers::endOutputOptionsEncrypt()
{
// QXXXQ
this->c_enc->endEncrypt();
this->c_enc = nullptr;
}
void
@ -371,147 +405,141 @@ Handlers::endInspect()
}
void
Handlers::beginTransform(JSON)
Handlers::beginOptionsAddAttachment(JSON)
{
// nothing needed
this->c_att = c_main->addAttachment();
}
void
Handlers::endTransform()
Handlers::endOptionsAddAttachment()
{
// nothing needed
this->c_att->endAddAttachment();
this->c_att = nullptr;
}
void
Handlers::beginModify(JSON)
Handlers::setupOptionsAddAttachmentPath(std::string const& key)
{
// nothing needed
addParameter(key, [this](char const* p) {
c_att->path(p);
});
}
void
Handlers::endModify()
Handlers::beginOptionsCopyAttachmentsFrom(JSON)
{
// nothing needed
this->c_copy_att = c_main->copyAttachmentsFrom();
}
void
Handlers::beginModifyAddAttachment(JSON)
Handlers::endOptionsCopyAttachmentsFrom()
{
this->c_copy_att->endCopyAttachmentsFrom();
this->c_copy_att = nullptr;
}
void
Handlers::setupOptionsCopyAttachmentsFromPath(std::string const& key)
{
addParameter(key, [this](char const* p) {
c_copy_att->path(p);
});
}
void
Handlers::setupOptionsCopyAttachmentsFromPassword(std::string const& key)
{
addParameter(key, [this](char const* p) {
c_copy_att->password(p);
});
}
void
Handlers::beginOptionsPages(JSON)
{
// QXXXQ
}
void
Handlers::endModifyAddAttachment()
Handlers::endOptionsPages()
{
// QXXXQ
}
void
Handlers::setupModifyAddAttachmentPath(std::string const& key)
Handlers::setupOptionsPagesFile(std::string const& key)
{
// QXXXQ setup
// handled in beginOptionsPages
}
void
Handlers::beginModifyCopyAttachmentsFrom(JSON)
Handlers::setupOptionsPagesPassword(std::string const& key)
{
// QXXXQ
// handled in beginOptionsPages
}
void
Handlers::endModifyCopyAttachmentsFrom()
Handlers::setupOptionsPagesRange(std::string const& key)
{
// QXXXQ
// handled in beginOptionsPages
}
void
Handlers::setupModifyCopyAttachmentsFromPath(std::string const& key)
Handlers::beginOptionsOverlay(JSON)
{
// QXXXQ setup
this->c_uo = c_main->overlay();
}
void
Handlers::setupModifyCopyAttachmentsFromPassword(std::string const& key)
Handlers::endOptionsOverlay()
{
// QXXXQ setup
c_uo->endUnderlayOverlay();
c_uo = nullptr;
}
void
Handlers::beginModifyPages(JSON)
Handlers::setupOptionsOverlayFile(std::string const& key)
{
// QXXXQ
addParameter(key, [this](char const* p) {
c_uo->path(p);
});
}
void
Handlers::endModifyPages()
Handlers::setupOptionsOverlayPassword(std::string const& key)
{
// QXXXQ
addParameter(key, [this](char const* p) {
c_uo->password(p);
});
}
void
Handlers::setupModifyPagesFile(std::string const& key)
Handlers::beginOptionsUnderlay(JSON)
{
// QXXXQ setup
this->c_uo = c_main->underlay();
}
void
Handlers::setupModifyPagesPassword(std::string const& key)
Handlers::endOptionsUnderlay()
{
// QXXXQ setup
c_uo->endUnderlayOverlay();
c_uo = nullptr;
}
void
Handlers::setupModifyPagesRange(std::string const& key)
Handlers::setupOptionsUnderlayFile(std::string const& key)
{
// QXXXQ setup
addParameter(key, [this](char const* p) {
c_uo->path(p);
});
}
void
Handlers::beginModifyOverlay(JSON)
Handlers::setupOptionsUnderlayPassword(std::string const& key)
{
// QXXXQ
}
void
Handlers::endModifyOverlay()
{
// QXXXQ
}
void
Handlers::setupModifyOverlayFile(std::string const& key)
{
// QXXXQ setup
}
void
Handlers::setupModifyOverlayPassword(std::string const& key)
{
// QXXXQ setup
}
void
Handlers::beginModifyUnderlay(JSON)
{
// QXXXQ
}
void
Handlers::endModifyUnderlay()
{
// QXXXQ
}
void
Handlers::setupModifyUnderlayFile(std::string const& key)
{
// QXXXQ setup
}
void
Handlers::setupModifyUnderlayPassword(std::string const& key)
{
// QXXXQ setup
addParameter(key, [this](char const* p) {
c_uo->password(p);
});
}
void

View File

@ -24,31 +24,27 @@ void beginOutputOptionsEncrypt128bit(JSON);
void endOutputOptionsEncrypt128bit();
void beginOutputOptionsEncrypt256bit(JSON);
void endOutputOptionsEncrypt256bit();
void beginOptions(JSON);
void endOptions();
void beginInspect(JSON);
void endInspect();
void beginTransform(JSON);
void endTransform();
void beginModify(JSON);
void endModify();
void beginModifyAddAttachment(JSON);
void endModifyAddAttachment();
void setupModifyAddAttachmentPath(std::string const&);
void beginModifyCopyAttachmentsFrom(JSON);
void endModifyCopyAttachmentsFrom();
void setupModifyCopyAttachmentsFromPath(std::string const&);
void setupModifyCopyAttachmentsFromPassword(std::string const&);
void beginModifyPages(JSON);
void endModifyPages();
void setupModifyPagesFile(std::string const&);
void setupModifyPagesPassword(std::string const&);
void setupModifyPagesRange(std::string const&);
void beginModifyOverlay(JSON);
void endModifyOverlay();
void setupModifyOverlayFile(std::string const&);
void setupModifyOverlayPassword(std::string const&);
void beginModifyUnderlay(JSON);
void endModifyUnderlay();
void setupModifyUnderlayFile(std::string const&);
void setupModifyUnderlayPassword(std::string const&);
void beginOptions(JSON);
void endOptions();
void beginOptionsAddAttachment(JSON);
void endOptionsAddAttachment();
void setupOptionsAddAttachmentPath(std::string const&);
void beginOptionsCopyAttachmentsFrom(JSON);
void endOptionsCopyAttachmentsFrom();
void setupOptionsCopyAttachmentsFromPath(std::string const&);
void setupOptionsCopyAttachmentsFromPassword(std::string const&);
void beginOptionsPages(JSON);
void endOptionsPages();
void setupOptionsPagesFile(std::string const&);
void setupOptionsPagesPassword(std::string const&);
void setupOptionsPagesRange(std::string const&);
void beginOptionsOverlay(JSON);
void endOptionsOverlay();
void setupOptionsOverlayFile(std::string const&);
void setupOptionsOverlayPassword(std::string const&);
void beginOptionsUnderlay(JSON);
void endOptionsUnderlay();
void setupOptionsUnderlayFile(std::string const&);
void setupOptionsUnderlayPassword(std::string const&);

View File

@ -83,20 +83,6 @@ endDict(); // .output.options.encrypt.256bit
endDict(); // .output.options.encrypt
endDict(); // .output.options
endDict(); // .output
beginDict("options", bindJSON(&Handlers::beginOptions), bindBare(&Handlers::endOptions)); // .options
addBare("allowWeakCrypto", [this]() { c_main->allowWeakCrypto(); });
addBare("deterministicId", [this]() { c_main->deterministicId(); });
addChoices("keepFilesOpen", yn_choices, [this](char const* p) { c_main->keepFilesOpen(p); });
addParameter("keepFilesOpenThreshold", [this](char const* p) { c_main->keepFilesOpenThreshold(p); });
addBare("noWarn", [this]() { c_main->noWarn(); });
addBare("verbose", [this]() { c_main->verbose(); });
addBare("warningExit0", [this]() { c_main->warningExit0(); });
addBare("ignoreXrefStreams", [this]() { c_main->ignoreXrefStreams(); });
addBare("passwordIsHexKey", [this]() { c_main->passwordIsHexKey(); });
addChoices("passwordMode", password_mode_choices, [this](char const* p) { c_main->passwordMode(p); });
addBare("suppressPasswordRecovery", [this]() { c_main->suppressPasswordRecovery(); });
addBare("suppressRecovery", [this]() { c_main->suppressRecovery(); });
endDict(); // .options
beginDict("inspect", bindJSON(&Handlers::beginInspect), bindBare(&Handlers::endInspect)); // .inspect
addBare("check", [this]() { c_main->check(); });
addBare("checkLinearization", [this]() { c_main->checkLinearization(); });
@ -118,16 +104,26 @@ addBare("json", [this]() { c_main->json(); });
addChoices("jsonKey", json_key_choices, [this](char const* p) { c_main->jsonKey(p); });
addParameter("jsonObject", [this](char const* p) { c_main->jsonObject(p); });
endDict(); // .inspect
beginDict("transform", bindJSON(&Handlers::beginTransform), bindBare(&Handlers::endTransform)); // .transform
beginDict("options", bindJSON(&Handlers::beginOptions), bindBare(&Handlers::endOptions)); // .options
addBare("allowWeakCrypto", [this]() { c_main->allowWeakCrypto(); });
addBare("deterministicId", [this]() { c_main->deterministicId(); });
addChoices("keepFilesOpen", yn_choices, [this](char const* p) { c_main->keepFilesOpen(p); });
addParameter("keepFilesOpenThreshold", [this](char const* p) { c_main->keepFilesOpenThreshold(p); });
addBare("noWarn", [this]() { c_main->noWarn(); });
addBare("verbose", [this]() { c_main->verbose(); });
addBare("warningExit0", [this]() { c_main->warningExit0(); });
addBare("ignoreXrefStreams", [this]() { c_main->ignoreXrefStreams(); });
addBare("passwordIsHexKey", [this]() { c_main->passwordIsHexKey(); });
addChoices("passwordMode", password_mode_choices, [this](char const* p) { c_main->passwordMode(p); });
addBare("suppressPasswordRecovery", [this]() { c_main->suppressPasswordRecovery(); });
addBare("suppressRecovery", [this]() { c_main->suppressRecovery(); });
addBare("coalesceContents", [this]() { c_main->coalesceContents(); });
addParameter("compressionLevel", [this](char const* p) { c_main->compressionLevel(p); });
addBare("externalizeInlineImages", [this]() { c_main->externalizeInlineImages(); });
addParameter("iiMinBytes", [this](char const* p) { c_main->iiMinBytes(p); });
addChoices("removeUnreferencedResources", remove_unref_choices, [this](char const* p) { c_main->removeUnreferencedResources(p); });
endDict(); // .transform
beginDict("modify", bindJSON(&Handlers::beginModify), bindBare(&Handlers::endModify)); // .modify
beginDict("addAttachment", bindJSON(&Handlers::beginModifyAddAttachment), bindBare(&Handlers::endModifyAddAttachment)); // .modify.addAttachment
doSetup("path", bindSetup(&Handlers::setupModifyAddAttachmentPath));
beginDict("addAttachment", bindJSON(&Handlers::beginOptionsAddAttachment), bindBare(&Handlers::endOptionsAddAttachment)); // .options.addAttachment
doSetup("path", bindSetup(&Handlers::setupOptionsAddAttachmentPath));
addParameter("creationdate", [this](char const* p) { c_att->creationdate(p); });
addParameter("description", [this](char const* p) { c_att->description(p); });
addParameter("filename", [this](char const* p) { c_att->filename(p); });
@ -135,13 +131,13 @@ addParameter("key", [this](char const* p) { c_att->key(p); });
addParameter("mimetype", [this](char const* p) { c_att->mimetype(p); });
addParameter("moddate", [this](char const* p) { c_att->moddate(p); });
addBare("replace", [this]() { c_att->replace(); });
endDict(); // .modify.addAttachment
endDict(); // .options.addAttachment
addParameter("removeAttachment", [this](char const* p) { c_main->removeAttachment(p); });
beginDict("copyAttachmentsFrom", bindJSON(&Handlers::beginModifyCopyAttachmentsFrom), bindBare(&Handlers::endModifyCopyAttachmentsFrom)); // .modify.copyAttachmentsFrom
doSetup("path", bindSetup(&Handlers::setupModifyCopyAttachmentsFromPath));
doSetup("password", bindSetup(&Handlers::setupModifyCopyAttachmentsFromPassword));
beginDict("copyAttachmentsFrom", bindJSON(&Handlers::beginOptionsCopyAttachmentsFrom), bindBare(&Handlers::endOptionsCopyAttachmentsFrom)); // .options.copyAttachmentsFrom
doSetup("path", bindSetup(&Handlers::setupOptionsCopyAttachmentsFromPath));
doSetup("password", bindSetup(&Handlers::setupOptionsCopyAttachmentsFromPassword));
addParameter("prefix", [this](char const* p) { c_copy_att->prefix(p); });
endDict(); // .modify.copyAttachmentsFrom
endDict(); // .options.copyAttachmentsFrom
addParameter("collate", [this](char const* p) { c_main->collate(p); });
addChoices("flattenAnnotations", flatten_choices, [this](char const* p) { c_main->flattenAnnotations(p); });
addBare("flattenRotation", [this]() { c_main->flattenRotation(); });
@ -151,25 +147,25 @@ addParameter("oiMinArea", [this](char const* p) { c_main->oiMinArea(p); });
addParameter("oiMinHeight", [this](char const* p) { c_main->oiMinHeight(p); });
addParameter("oiMinWidth", [this](char const* p) { c_main->oiMinWidth(p); });
addBare("optimizeImages", [this]() { c_main->optimizeImages(); });
beginDict("pages", bindJSON(&Handlers::beginModifyPages), bindBare(&Handlers::endModifyPages)); // .modify.pages
doSetup("file", bindSetup(&Handlers::setupModifyPagesFile));
doSetup("password", bindSetup(&Handlers::setupModifyPagesPassword));
doSetup("range", bindSetup(&Handlers::setupModifyPagesRange));
endDict(); // .modify.pages
beginDict("pages", bindJSON(&Handlers::beginOptionsPages), bindBare(&Handlers::endOptionsPages)); // .options.pages
doSetup("file", bindSetup(&Handlers::setupOptionsPagesFile));
doSetup("password", bindSetup(&Handlers::setupOptionsPagesPassword));
doSetup("range", bindSetup(&Handlers::setupOptionsPagesRange));
endDict(); // .options.pages
addBare("removePageLabels", [this]() { c_main->removePageLabels(); });
addParameter("rotate", [this](char const* p) { c_main->rotate(p); });
beginDict("overlay", bindJSON(&Handlers::beginModifyOverlay), bindBare(&Handlers::endModifyOverlay)); // .modify.overlay
doSetup("file", bindSetup(&Handlers::setupModifyOverlayFile));
doSetup("password", bindSetup(&Handlers::setupModifyOverlayPassword));
beginDict("overlay", bindJSON(&Handlers::beginOptionsOverlay), bindBare(&Handlers::endOptionsOverlay)); // .options.overlay
doSetup("file", bindSetup(&Handlers::setupOptionsOverlayFile));
doSetup("password", bindSetup(&Handlers::setupOptionsOverlayPassword));
addParameter("from", [this](char const* p) { c_uo->from(p); });
addParameter("repeat", [this](char const* p) { c_uo->repeat(p); });
addParameter("to", [this](char const* p) { c_uo->to(p); });
endDict(); // .modify.overlay
beginDict("underlay", bindJSON(&Handlers::beginModifyUnderlay), bindBare(&Handlers::endModifyUnderlay)); // .modify.underlay
doSetup("file", bindSetup(&Handlers::setupModifyUnderlayFile));
doSetup("password", bindSetup(&Handlers::setupModifyUnderlayPassword));
endDict(); // .options.overlay
beginDict("underlay", bindJSON(&Handlers::beginOptionsUnderlay), bindBare(&Handlers::endOptionsUnderlay)); // .options.underlay
doSetup("file", bindSetup(&Handlers::setupOptionsUnderlayFile));
doSetup("password", bindSetup(&Handlers::setupOptionsUnderlayPassword));
addParameter("from", [this](char const* p) { c_uo->from(p); });
addParameter("repeat", [this](char const* p) { c_uo->repeat(p); });
addParameter("to", [this](char const* p) { c_uo->to(p); });
endDict(); // .modify.underlay
endDict(); // .modify
endDict(); // .options.underlay
endDict(); // .options

View File

@ -68,20 +68,6 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({
}
}
},
"options": {
"allowWeakCrypto": "allow insecure cryptographic algorithms",
"deterministicId": "generate ID deterministically",
"keepFilesOpen": "manage keeping multiple files open",
"keepFilesOpenThreshold": "set threshold for keepFilesOpen",
"noWarn": "suppress printing of warning messages",
"verbose": "print additional information",
"warningExit0": "exit 0 even with warnings",
"ignoreXrefStreams": "use xref tables rather than streams",
"passwordIsHexKey": "provide hex-encoded encryption key",
"passwordMode": "tweak how qpdf encodes passwords",
"suppressPasswordRecovery": "don't try different password encodings",
"suppressRecovery": "suppress error recovery"
},
"inspect": {
"check": "partially check whether PDF is valid",
"checkLinearization": "check linearization tables",
@ -107,14 +93,24 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({
null
]
},
"transform": {
"options": {
"allowWeakCrypto": "allow insecure cryptographic algorithms",
"deterministicId": "generate ID deterministically",
"keepFilesOpen": "manage keeping multiple files open",
"keepFilesOpenThreshold": "set threshold for keepFilesOpen",
"noWarn": "suppress printing of warning messages",
"verbose": "print additional information",
"warningExit0": "exit 0 even with warnings",
"ignoreXrefStreams": "use xref tables rather than streams",
"passwordIsHexKey": "provide hex-encoded encryption key",
"passwordMode": "tweak how qpdf encodes passwords",
"suppressPasswordRecovery": "don't try different password encodings",
"suppressRecovery": "suppress error recovery",
"coalesceContents": "combine content streams",
"compressionLevel": "set compression level for flate",
"externalizeInlineImages": "convert inline to regular images",
"iiMinBytes": "set minimum size for externalizeInlineImages",
"removeUnreferencedResources": "remove unreferenced page resources"
},
"modify": {
"removeUnreferencedResources": "remove unreferenced page resources",
"addAttachment": [
{
"path": "attachment to add",