From 0a354af02cf51aeb1602596988c8f826b47b3a81 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 25 Jan 2022 16:37:17 -0500 Subject: [PATCH] QPDFJob: convert AddAttachment handlers --- generate_auto_job | 7 -- include/qpdf/QPDFJob.hh | 55 +++++++++----- include/qpdf/auto_job_c_att.hh | 13 ++++ job.sums | 11 +-- job.yml | 5 +- libqpdf/QPDFJob_argv.cc | 91 ++--------------------- libqpdf/QPDFJob_config.cc | 124 +++++++++++++++++++++++++++++++- libqpdf/qpdf/auto_job_decl.hh | 7 -- libqpdf/qpdf/auto_job_init.hh | 14 ++-- libqpdf/qpdf/auto_job_schema.hh | 4 +- 10 files changed, 197 insertions(+), 134 deletions(-) create mode 100644 include/qpdf/auto_job_c_att.hh diff --git a/generate_auto_job b/generate_auto_job index ed2a9b82..94695277 100755 --- a/generate_auto_job +++ b/generate_auto_job @@ -52,19 +52,13 @@ not_yet = set([ 'annotate', 'assemble', 'cleartext-metadata', - 'creationdate', 'decode-level', - 'description', 'extract', - 'filename', 'force-R5', 'force-V4', 'form', 'from', 'job-json-file', - 'key', - 'mimetype', - 'moddate', 'modify', 'modify-other', 'object-streams', @@ -73,7 +67,6 @@ not_yet = set([ 'print', 'remove-unreferenced-resources', 'repeat', - 'replace', 'rotate', 'show-object', 'stream-data', diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index 18f1a28e..734f5f45 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -108,14 +108,49 @@ class QPDFJob std::string prefix; }; + struct AddAttachment + { + AddAttachment() : + replace(false) + { + } + + std::string path; + std::string key; + std::string filename; + std::string creationdate; + std::string moddate; + std::string mimetype; + std::string description; + bool replace; + }; + public: class Config; + + class AttConfig + { + friend class QPDFJob; + friend class Config; + public: + QPDF_DLL AttConfig& path(char const* parameter); + +# include + + private: + AttConfig(Config&); + AttConfig(AttConfig const&) = delete; + + Config& config; + AddAttachment att; + }; + class CopyAttConfig { friend class QPDFJob; friend class Config; public: - QPDF_DLL CopyAttConfig& filename(char const* parameter); + QPDF_DLL CopyAttConfig& path(char const* parameter); # include @@ -134,6 +169,7 @@ class QPDFJob public: QPDF_DLL std::shared_ptr copyAttachmentsFrom(); + std::shared_ptr addAttachment(); # include @@ -244,23 +280,6 @@ class QPDFJob std::vector repeat_pagenos; }; - struct AddAttachment - { - AddAttachment() : - replace(false) - { - } - - std::string path; - std::string key; - std::string filename; - std::string creationdate; - std::string moddate; - std::string mimetype; - std::string description; - bool replace; - }; - enum remove_unref_e { re_auto, re_yes, re_no }; std::shared_ptr password; diff --git a/include/qpdf/auto_job_c_att.hh b/include/qpdf/auto_job_c_att.hh new file mode 100644 index 00000000..ac0f4223 --- /dev/null +++ b/include/qpdf/auto_job_c_att.hh @@ -0,0 +1,13 @@ +// +// This file is automatically generated by generate_auto_job. +// Edits will be automatically overwritten if the build is +// run in maintainer mode. +// +QPDF_DLL Config& end(); +QPDF_DLL AttConfig& replace(); +QPDF_DLL AttConfig& key(char const* parameter); +QPDF_DLL AttConfig& filename(char const* parameter); +QPDF_DLL AttConfig& creationdate(char const* parameter); +QPDF_DLL AttConfig& moddate(char const* parameter); +QPDF_DLL AttConfig& mimetype(char const* parameter); +QPDF_DLL AttConfig& description(char const* parameter); diff --git a/job.sums b/job.sums index d3de2828..78fc450a 100644 --- a/job.sums +++ b/job.sums @@ -1,11 +1,12 @@ # Generated by generate_auto_job -generate_auto_job 36a09904317400caa4a2434f5b2acd59c20905a28479f45bba5e1fcfc654e697 +generate_auto_job d9f75a50dd4e503ede676bad54f80f856de096da7f3ad0e4594b0d09a6e1215d +include/qpdf/auto_job_c_att.hh ecc3f8f711b486b491e811176362a90c022eb225ff12157df3a10ca021be87b1 include/qpdf/auto_job_c_copy_att.hh caffae3d1faf2cd92a07ba77da638cce31da3e074a047918834195c0f3ed508a include/qpdf/auto_job_c_main.hh 5fdd9c85aa295a3caec467b9607fe82c874cd3aaeb7806b9d18074f7b96fd085 -job.yml 55d272cca0657e1f96ca92f5253edb6c6e24e6ea19e37690446d2111adc13f91 -libqpdf/qpdf/auto_job_decl.hh e9844137bf53345f2c6973378b314a2510ebce83ac8ceb378588cd6afdd87c06 +job.yml e649f7dbb3748584f338b330043336ce4a4d51a34b00b42caa89dcfbc7bdcb84 +libqpdf/qpdf/auto_job_decl.hh 38f7462e34fea7d46d5e5519ac1742be6e57ea6f66c47b37d5425f3a2b9ca536 libqpdf/qpdf/auto_job_help.hh 383eea80e2c185ef5295fc126246457a7ceeffea759fdb90bb2e6727532ea538 -libqpdf/qpdf/auto_job_init.hh e65119793c329630aa243ff20907443f8eaf54c29d02737a598f29bba64b0bf5 -libqpdf/qpdf/auto_job_schema.hh c91a4e182e088797b70dda94af03ca32d360f3564890132da2a8bdc3c4432423 +libqpdf/qpdf/auto_job_init.hh b49d839078d84398142f8f14bdae8a71f44fbff13cdf7b350b84ef2410aaa6a3 +libqpdf/qpdf/auto_job_schema.hh 6e6d72e99dacd02c22d9ac70f4dc78a935f879d2a16c89f07f2bdfa936cc2ae3 manual/_ext/qpdf.py 855fe12de5af7a10bb24be6ecc4d5dff4c84ac58cf388a13be6bbb394346a67d manual/cli.rst 68122ff8179c10df3fe6d577adde4973c346f7866ba9a511bab5a6e6f292a6f1 diff --git a/job.yml b/job.yml index 388360ea..01ad3630 100644 --- a/job.yml +++ b/job.yml @@ -203,6 +203,7 @@ options: repeat: page-range password: password - table: attachment + config: c_att prefix: Att positional: true bare: @@ -340,7 +341,7 @@ json: remove-unreferenced-resources: _modify: add-attachment: - - file: "attachment to add" + - path: "attachment to add" creationdate: description: filename: @@ -350,7 +351,7 @@ json: replace: remove-attachment: copy-attachments-from: - - file: "attachment source filename" + - path: "attachment source filename" CopyAtt.password: prefix: collate: diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc index af7ce13f..a32818ba 100644 --- a/libqpdf/QPDFJob_argv.cc +++ b/libqpdf/QPDFJob_argv.cc @@ -45,6 +45,7 @@ namespace QPDFJob& o; std::shared_ptr c_main; std::shared_ptr c_copy_att; + std::shared_ptr c_att; std::vector accumulated_args; // points to member in ap char* pages_password; }; @@ -441,7 +442,7 @@ ArgParser::argRotate(char* parameter) void ArgParser::argAddAttachment() { - o.attachments_to_add.push_back(QPDFJob::AddAttachment()); + this->c_att = c_main->addAttachment(); this->ap.selectOptionTable(O_ATTACHMENT); } @@ -792,100 +793,20 @@ ArgParser::argEndUnderlayOverlay() void ArgParser::argAttPositional(char* arg) { - o.attachments_to_add.back().path = arg; -} - -void -ArgParser::argAttKey(char* parameter) -{ - o.attachments_to_add.back().key = parameter; -} - -void -ArgParser::argAttFilename(char* parameter) -{ - o.attachments_to_add.back().filename = parameter; -} - -void -ArgParser::argAttCreationdate(char* parameter) -{ - if (! QUtil::pdf_time_to_qpdf_time(parameter)) - { - usage(std::string(parameter) + " is not a valid PDF timestamp"); - } - o.attachments_to_add.back().creationdate = parameter; -} - -void -ArgParser::argAttModdate(char* parameter) -{ - if (! QUtil::pdf_time_to_qpdf_time(parameter)) - { - usage(std::string(parameter) + " is not a valid PDF timestamp"); - } - o.attachments_to_add.back().moddate = parameter; -} - -void -ArgParser::argAttMimetype(char* parameter) -{ - if (strchr(parameter, '/') == nullptr) - { - usage("mime type should be specified as type/subtype"); - } - o.attachments_to_add.back().mimetype = parameter; -} - -void -ArgParser::argAttDescription(char* parameter) -{ - o.attachments_to_add.back().description = parameter; -} - -void -ArgParser::argAttReplace() -{ - o.attachments_to_add.back().replace = true; + c_att->path(arg); } void ArgParser::argEndAttachment() { - static std::string now = QUtil::qpdf_time_to_pdf_time( - QUtil::get_current_qpdf_time()); - auto& cur = o.attachments_to_add.back(); - if (cur.path.empty()) - { - usage("add attachment: no path specified"); - } - std::string last_element = QUtil::path_basename(cur.path); - if (last_element.empty()) - { - usage("path for --add-attachment may not be empty"); - } - if (cur.filename.empty()) - { - cur.filename = last_element; - } - if (cur.key.empty()) - { - cur.key = last_element; - } - if (cur.creationdate.empty()) - { - cur.creationdate = now; - } - if (cur.moddate.empty()) - { - cur.moddate = now; - } + c_att->end(); + c_att = nullptr; } void ArgParser::argCopyAttPositional(char* arg) { - c_copy_att->filename(arg); + c_copy_att->path(arg); } void diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc index 34f15b9f..ad970aa4 100644 --- a/libqpdf/QPDFJob_config.cc +++ b/libqpdf/QPDFJob_config.cc @@ -509,7 +509,7 @@ QPDFJob::CopyAttConfig::CopyAttConfig(Config& c) : } QPDFJob::CopyAttConfig& -QPDFJob::CopyAttConfig::filename(char const* parameter) +QPDFJob::CopyAttConfig::path(char const* parameter) { this->caf.path = parameter; return *this; @@ -541,3 +541,125 @@ QPDFJob::CopyAttConfig::end() this->config.o.attachments_to_copy.push_back(this->caf); return this->config; } + +QPDFJob::AttConfig::AttConfig(Config& c) : + config(c) +{ +} + +std::shared_ptr +QPDFJob::Config::addAttachment() +{ + return std::shared_ptr(new AttConfig(*this)); +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::path(char const* parameter) +{ + this->att.path = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::key(char const* parameter) +{ + this->att.key = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::filename(char const* parameter) +{ + this->att.filename = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::creationdate(char const* parameter) +{ + if (! QUtil::pdf_time_to_qpdf_time(parameter)) + { + // QXXXQ + throw std::runtime_error( + std::string(parameter) + " is not a valid PDF timestamp"); + } + this->att.creationdate = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::moddate(char const* parameter) +{ + if (! QUtil::pdf_time_to_qpdf_time(parameter)) + { + // QXXXQ + throw std::runtime_error( + std::string(parameter) + " is not a valid PDF timestamp"); + } + this->att.moddate = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::mimetype(char const* parameter) +{ + if (strchr(parameter, '/') == nullptr) + { + // QXXXQ + throw std::runtime_error( + "mime type should be specified as type/subtype"); + } + this->att.mimetype = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::description(char const* parameter) +{ + this->att.description = parameter; + return *this; +} + +QPDFJob::AttConfig& +QPDFJob::AttConfig::replace() +{ + this->att.replace = true; + return *this; +} + +QPDFJob::Config& +QPDFJob::AttConfig::end() +{ + // QXXXQ runtime_error + + static std::string now = QUtil::qpdf_time_to_pdf_time( + QUtil::get_current_qpdf_time()); + if (this->att.path.empty()) + { + throw std::runtime_error("add attachment: no path specified"); + } + std::string last_element = QUtil::path_basename(this->att.path); + if (last_element.empty()) + { + throw std::runtime_error("path for --add-attachment may not be empty"); + } + if (this->att.filename.empty()) + { + this->att.filename = last_element; + } + if (this->att.key.empty()) + { + this->att.key = last_element; + } + if (this->att.creationdate.empty()) + { + this->att.creationdate = now; + } + if (this->att.moddate.empty()) + { + this->att.moddate = now; + } + + this->config.o.attachments_to_add.push_back(this->att); + return this->config; +} diff --git a/libqpdf/qpdf/auto_job_decl.hh b/libqpdf/qpdf/auto_job_decl.hh index 1ea25372..98e1d6e3 100644 --- a/libqpdf/qpdf/auto_job_decl.hh +++ b/libqpdf/qpdf/auto_job_decl.hh @@ -65,13 +65,6 @@ void argUORepeat(char *); void argUOPassword(char *); void argEndUnderlayOverlay(); void argAttPositional(char*); -void argAttReplace(); -void argAttKey(char *); -void argAttFilename(char *); -void argAttCreationdate(char *); -void argAttModdate(char *); -void argAttMimetype(char *); -void argAttDescription(char *); void argEndAttachment(); void argCopyAttPositional(char*); void argEndCopyAttachment(); diff --git a/libqpdf/qpdf/auto_job_init.hh b/libqpdf/qpdf/auto_job_init.hh index 7ceff2ae..d6bb63f3 100644 --- a/libqpdf/qpdf/auto_job_init.hh +++ b/libqpdf/qpdf/auto_job_init.hh @@ -143,13 +143,13 @@ this->ap.addRequiredParameter("repeat", p(&ArgParser::argUORepeat), "page-range" this->ap.addRequiredParameter("password", p(&ArgParser::argUOPassword), "password"); this->ap.registerOptionTable("attachment", b(&ArgParser::argEndAttachment)); this->ap.addPositional(p(&ArgParser::argAttPositional)); -this->ap.addBare("replace", b(&ArgParser::argAttReplace)); -this->ap.addRequiredParameter("key", p(&ArgParser::argAttKey), "attachment-key"); -this->ap.addRequiredParameter("filename", p(&ArgParser::argAttFilename), "filename"); -this->ap.addRequiredParameter("creationdate", p(&ArgParser::argAttCreationdate), "creation-date"); -this->ap.addRequiredParameter("moddate", p(&ArgParser::argAttModdate), "modification-date"); -this->ap.addRequiredParameter("mimetype", p(&ArgParser::argAttMimetype), "mime/type"); -this->ap.addRequiredParameter("description", p(&ArgParser::argAttDescription), "description"); +this->ap.addBare("replace", [this](){c_att->replace();}); +this->ap.addRequiredParameter("key", [this](char *x){c_att->key(x);}, "attachment-key"); +this->ap.addRequiredParameter("filename", [this](char *x){c_att->filename(x);}, "filename"); +this->ap.addRequiredParameter("creationdate", [this](char *x){c_att->creationdate(x);}, "creation-date"); +this->ap.addRequiredParameter("moddate", [this](char *x){c_att->moddate(x);}, "modification-date"); +this->ap.addRequiredParameter("mimetype", [this](char *x){c_att->mimetype(x);}, "mime/type"); +this->ap.addRequiredParameter("description", [this](char *x){c_att->description(x);}, "description"); this->ap.registerOptionTable("copy attachment", b(&ArgParser::argEndCopyAttachment)); this->ap.addPositional(p(&ArgParser::argCopyAttPositional)); this->ap.addRequiredParameter("prefix", [this](char *x){c_copy_att->prefix(x);}, "prefix"); diff --git a/libqpdf/qpdf/auto_job_schema.hh b/libqpdf/qpdf/auto_job_schema.hh index 9ecdc507..7fe018af 100644 --- a/libqpdf/qpdf/auto_job_schema.hh +++ b/libqpdf/qpdf/auto_job_schema.hh @@ -122,7 +122,7 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({ "modify": { "addAttachment": [ { - "file": "attachment to add", + "path": "attachment to add", "creationdate": "set attachment's creation date", "description": "set attachment's description", "filename": "set attachment's displayed filename", @@ -135,7 +135,7 @@ static constexpr char const* JOB_SCHEMA_DATA = R"({ "removeAttachment": "remove an embedded file", "copyAttachmentsFrom": [ { - "file": "attachment source filename", + "path": "attachment source filename", "password": "specify password", "prefix": "key prefix for copying attachments" }