diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index 64075bc1..e16e5ca1 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -43,6 +43,13 @@ class QPDFWriter; class QPDFJob { public: + // Exit codes -- returned by getExitCode() after calling run() + static int constexpr EXIT_ERROR = 2; + static int constexpr EXIT_WARNING = 3; + // For is-encrypted and requires-password + static int constexpr EXIT_IS_NOT_ENCRYPTED = 2; + static int constexpr EXIT_CORRECT_PASSWORD = 3; + // QPDFUsage is thrown if there are any usage-like errors when // calling Config methods. QPDF_DLL @@ -345,17 +352,6 @@ class QPDFJob QPDF_DLL std::shared_ptr config(); - // Options for helping the qpdf CLI use the correct edit code and - // properly report warnings. - QPDF_DLL - bool suppressWarnings(); - QPDF_DLL - bool warningsExitZero(); - QPDF_DLL - bool checkRequiresPassword(); - QPDF_DLL - bool checkIsEncrypted(); - // Execute the job QPDF_DLL void run(); @@ -364,7 +360,17 @@ class QPDFJob // run() is called. QPDF_DLL - bool hasWarnings(); + bool hasWarnings() const; + + // Return one of the EXIT_* constants defined at the top of the + // class declaration. This may be called after run() when run() + // did not throw an exception. Takes into consideration whether + // isEncrypted or requiresPassword was called. Note that this + // function does not know whether run() threw an exception, so + // code that uses this to determine how to exit should explicitly + // use EXIT_ERROR if run() threw an exception. + QPDF_DLL + int getExitCode() const; // Return value is bitwise OR of values from qpdf_encryption_status_e QPDF_DLL diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index a06f87bc..bea8e358 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -629,10 +629,28 @@ QPDFJob::run() { this->m->warnings = true; } + if (this->m->warnings && (! this->m->suppress_warnings)) + { + if (createsOutput()) + { + (*this->m->cerr) + << this->m->message_prefix + << ": operation succeeded with warnings;" + << " resulting file may have some problems" + << std::endl; + } + else + { + (*this->m->cerr) + << this->m->message_prefix + << ": operation succeeded with warnings" + << std::endl; + } + } } bool -QPDFJob::hasWarnings() +QPDFJob::hasWarnings() const { return this->m->warnings; } @@ -643,6 +661,51 @@ QPDFJob::createsOutput() const return ((m->outfilename != nullptr) || m->replace_input); } +int +QPDFJob::getExitCode() const +{ + if (this->m->check_is_encrypted) + { + if (this->m->encryption_status & qpdf_es_encrypted) + { + QTC::TC("qpdf", "qpdf check encrypted encrypted"); + return 0; + } + else + { + QTC::TC("qpdf", "qpdf check encrypted not encrypted"); + return EXIT_IS_NOT_ENCRYPTED; + } + } + else if (this->m->check_requires_password) + { + if (this->m->encryption_status & qpdf_es_encrypted) + { + if (this->m->encryption_status & qpdf_es_password_incorrect) + { + QTC::TC("qpdf", "qpdf check password password incorrect"); + return 0; + } + else + { + QTC::TC("qpdf", "qpdf check password password correct"); + return EXIT_CORRECT_PASSWORD; + } + } + else + { + QTC::TC("qpdf", "qpdf check password not encrypted"); + return EXIT_IS_NOT_ENCRYPTED; + } + } + + if (this->m->warnings && (! this->m->warnings_exit_zero)) + { + return EXIT_WARNING; + } + return 0; +} + void QPDFJob::checkConfiguration() { @@ -726,30 +789,6 @@ QPDFJob::checkConfiguration() } } -bool -QPDFJob::suppressWarnings() -{ - return this->m->suppress_warnings; -} - -bool -QPDFJob::warningsExitZero() -{ - return this->m->warnings_exit_zero; -} - -bool -QPDFJob::checkRequiresPassword() -{ - return this->m->check_requires_password; -} - -bool -QPDFJob::checkIsEncrypted() -{ - return this->m->check_is_encrypted; -} - unsigned long QPDFJob::getEncryptionStatus() { diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index 953d0291..d2c576a4 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -1,5 +1,4 @@ #include -#include #include #include @@ -8,13 +7,6 @@ #include #include -static int constexpr EXIT_ERROR = 2; -static int constexpr EXIT_WARNING = 3; - -// For is-encrypted and requires-password -static int constexpr EXIT_IS_NOT_ENCRYPTED = 2; -static int constexpr EXIT_CORRECT_PASSWORD = 3; - static char const* whoami = 0; static void usageExit(std::string const& msg) @@ -33,7 +25,7 @@ static void usageExit(std::string const& msg) << " " << whoami << "--help general help and a topic list" << std::endl << std::endl; - exit(EXIT_ERROR); + exit(QPDFJob::EXIT_ERROR); } int realmain(int argc, char* argv[]) @@ -48,8 +40,6 @@ int realmain(int argc, char* argv[]) } QPDFJob j; - - bool errors = false; try { // See "HOW TO ADD A COMMAND-LINE ARGUMENT" in README-maintainer. @@ -63,74 +53,9 @@ int realmain(int argc, char* argv[]) catch (std::exception& e) { std::cerr << whoami << ": " << e.what() << std::endl; - errors = true; + return QPDFJob::EXIT_ERROR; } - - bool warnings = j.hasWarnings(); - if (warnings) - { - if (! j.suppressWarnings()) - { - if (j.createsOutput()) - { - std::cerr << whoami << ": operation succeeded with warnings;" - << " resulting file may have some problems" - << std::endl; - } - else - { - std::cerr << whoami << ": operation succeeded with warnings" - << std::endl; - } - } - // Still return with warning code even if warnings were - // suppressed, so leave warnings == true unless we've been - // specifically instructed to do otherwise. - if (j.warningsExitZero()) - { - warnings = false; - } - } - - unsigned long encryption_status = j.getEncryptionStatus(); - if (j.checkIsEncrypted()) - { - if (encryption_status & qpdf_es_encrypted) - { - QTC::TC("qpdf", "qpdf check encrypted encrypted"); - return 0; - } - else - { - QTC::TC("qpdf", "qpdf check encrypted not encrypted"); - return EXIT_IS_NOT_ENCRYPTED; - } - } - else if (j.checkRequiresPassword()) - { - if (encryption_status & qpdf_es_encrypted) - { - if (encryption_status & qpdf_es_password_incorrect) - { - QTC::TC("qpdf", "qpdf check password password incorrect"); - return 0; - } - else - { - QTC::TC("qpdf", "qpdf check password password correct"); - return EXIT_CORRECT_PASSWORD; - } - } - else - { - QTC::TC("qpdf", "qpdf check password not encrypted"); - return EXIT_IS_NOT_ENCRYPTED; - } - } - - return (errors ? EXIT_ERROR : - warnings ? EXIT_WARNING : - 0); + return j.getExitCode(); } #ifdef WINDOWS_WMAIN diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 4158b030..1f6d6b17 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -3182,6 +3182,9 @@ static void test_84(QPDF& pdf, char const* arg2) ->objectStreams("preserve") ->checkConfiguration(); j.run(); + assert(j.getExitCode() == 0); + assert(! j.hasWarnings()); + assert(j.getEncryptionStatus() == 0); } std::cout << "error caught by check" << std::endl;