2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-30 08:50:51 +00:00

QPDFJob increment: remove std::cout, std::cerr, whoami

Remove remaining temporary duplication of hard-coded values and direct
access to std::cout, std::cerr, and whoami in favor of parameters in
QPDFJob. This moves a few more static methods into QPDFJob member
functions.
This commit is contained in:
Jay Berkenbilt 2022-01-05 15:01:35 -05:00
parent 1ddf5b4b4b
commit 2f631997f2
2 changed files with 188 additions and 167 deletions

View File

@ -50,7 +50,7 @@ class QPDFJob
void setMessagePrefix(std::string const&); void setMessagePrefix(std::string const&);
// Override streams that errors and output go to. Defaults are // Override streams that errors and output go to. Defaults are
// std::cout and std::cerr. // std::cout and std::cerr. Pass nullptr to use the default.
QPDF_DLL QPDF_DLL
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream); void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
@ -183,6 +183,11 @@ class QPDFJob
void doInspection(QPDF& pdf); void doInspection(QPDF& pdf);
void showEncryption(QPDF& pdf); void showEncryption(QPDF& pdf);
void doCheck(QPDF& pdf); void doCheck(QPDF& pdf);
void doShowObj(QPDF& pdf);
void doShowPages(QPDF& pdf);
void doListAttachments(QPDF& pdf);
void setEncryptionOptions(QPDF&, QPDFWriter&);
void maybeFixWritePassword(int R, std::string& password);
enum remove_unref_e { re_auto, re_yes, re_no }; enum remove_unref_e { re_auto, re_yes, re_no };
@ -313,11 +318,11 @@ class QPDFJob
Members(); Members();
Members(Members const&) = delete; Members(Members const&) = delete;
std::string whoami; std::string message_prefix;
bool warnings; bool warnings;
bool creates_output; bool creates_output;
std::ostream* out_stream; std::ostream* cout;
std::ostream* err_stream; std::ostream* cerr;
unsigned long encryption_status; unsigned long encryption_status;
}; };
PointerHolder<Members> m; PointerHolder<Members> m;

View File

@ -34,10 +34,6 @@
#include <qpdf/QPDFWriter.hh> #include <qpdf/QPDFWriter.hh>
#include <qpdf/QIntC.hh> #include <qpdf/QIntC.hh>
// QXXXQ temporary for compilation
static char const* whoami = "qpdf";
// /QXXXQ
namespace namespace
{ {
class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider
@ -68,7 +64,8 @@ namespace
struct QPDFPageData struct QPDFPageData
{ {
QPDFPageData(std::string const& filename, QPDF* qpdf, char const* range); QPDFPageData(std::string const& filename,
QPDF* qpdf, char const* range);
QPDFPageData(QPDFPageData const& other, int page); QPDFPageData(QPDFPageData const& other, int page);
std::string filename; std::string filename;
@ -80,8 +77,11 @@ namespace
class ProgressReporter: public QPDFWriter::ProgressReporter class ProgressReporter: public QPDFWriter::ProgressReporter
{ {
public: public:
ProgressReporter(std::string const& whoami, char const* filename) : ProgressReporter(std::ostream& cout,
whoami(whoami), std::string const& prefix,
char const* filename) :
cout(cout),
prefix(prefix),
filename(filename) filename(filename)
{ {
} }
@ -91,7 +91,8 @@ namespace
virtual void reportProgress(int); virtual void reportProgress(int);
private: private:
std::string whoami; std::ostream& cout;
std::string prefix;
std::string filename; std::string filename;
}; };
} }
@ -127,17 +128,17 @@ QPDFPageData::QPDFPageData(QPDFPageData const& other, int page) :
void void
ProgressReporter::reportProgress(int percentage) ProgressReporter::reportProgress(int percentage)
{ {
std::cout << whoami << ": " << filename << ": write progress: " this->cout << prefix << ": " << filename << ": write progress: "
<< percentage << "%" << std::endl; << percentage << "%" << std::endl;
} }
QPDFJob::Members::Members() : QPDFJob::Members::Members() :
whoami("qpdf"), message_prefix("qpdf"),
warnings(false), warnings(false),
creates_output(false), creates_output(false),
out_stream(&std::cout), cout(&std::cout),
err_stream(&std::cerr), cerr(&std::cerr),
encryption_status(0) encryption_status(0)
{ {
} }
@ -246,25 +247,25 @@ QPDFJob::QPDFJob() :
} }
void void
QPDFJob::setMessagePrefix(std::string const& whoami) QPDFJob::setMessagePrefix(std::string const& message_prefix)
{ {
this->m->whoami = whoami; this->m->message_prefix = message_prefix;
} }
void void
QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err) QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
{ {
this->m->out_stream = out ? out : &std::cout; this->m->cout = out ? out : &std::cout;
this->m->err_stream = err ? err : &std::cerr; this->m->cerr = err ? err : &std::cerr;
} }
void void
QPDFJob::doIfVerbose( QPDFJob::doIfVerbose(
std::function<void(std::ostream&, std::string const& prefix)> fn) std::function<void(std::ostream&, std::string const& prefix)> fn)
{ {
if (this->verbose && (this->m->out_stream != nullptr)) if (this->verbose && (this->m->cout != nullptr))
{ {
fn(*(this->m->out_stream), this->m->whoami); fn(*(this->m->cout), this->m->message_prefix);
} }
} }
@ -344,57 +345,58 @@ QPDFJob::showEncryption(QPDF& pdf)
QPDF::encryption_method_e stream_method = QPDF::e_unknown; QPDF::encryption_method_e stream_method = QPDF::e_unknown;
QPDF::encryption_method_e string_method = QPDF::e_unknown; QPDF::encryption_method_e string_method = QPDF::e_unknown;
QPDF::encryption_method_e file_method = QPDF::e_unknown; QPDF::encryption_method_e file_method = QPDF::e_unknown;
auto& cout = *this->m->cout;
if (! pdf.isEncrypted(R, P, V, if (! pdf.isEncrypted(R, P, V,
stream_method, string_method, file_method)) stream_method, string_method, file_method))
{ {
std::cout << "File is not encrypted" << std::endl; cout << "File is not encrypted" << std::endl;
} }
else else
{ {
std::cout << "R = " << R << std::endl; cout << "R = " << R << std::endl;
std::cout << "P = " << P << std::endl; cout << "P = " << P << std::endl;
std::string user_password = pdf.getTrimmedUserPassword(); std::string user_password = pdf.getTrimmedUserPassword();
std::string encryption_key = pdf.getEncryptionKey(); std::string encryption_key = pdf.getEncryptionKey();
std::cout << "User password = " << user_password << std::endl; cout << "User password = " << user_password << std::endl;
if (o.show_encryption_key) if (o.show_encryption_key)
{ {
std::cout << "Encryption key = " cout << "Encryption key = "
<< QUtil::hex_encode(encryption_key) << std::endl; << QUtil::hex_encode(encryption_key) << std::endl;
} }
if (pdf.ownerPasswordMatched()) if (pdf.ownerPasswordMatched())
{ {
std::cout << "Supplied password is owner password" << std::endl; cout << "Supplied password is owner password" << std::endl;
} }
if (pdf.userPasswordMatched()) if (pdf.userPasswordMatched())
{ {
std::cout << "Supplied password is user password" << std::endl; cout << "Supplied password is user password" << std::endl;
} }
std::cout << "extract for accessibility: " cout << "extract for accessibility: "
<< show_bool(pdf.allowAccessibility()) << std::endl << show_bool(pdf.allowAccessibility()) << std::endl
<< "extract for any purpose: " << "extract for any purpose: "
<< show_bool(pdf.allowExtractAll()) << std::endl << show_bool(pdf.allowExtractAll()) << std::endl
<< "print low resolution: " << "print low resolution: "
<< show_bool(pdf.allowPrintLowRes()) << std::endl << show_bool(pdf.allowPrintLowRes()) << std::endl
<< "print high resolution: " << "print high resolution: "
<< show_bool(pdf.allowPrintHighRes()) << std::endl << show_bool(pdf.allowPrintHighRes()) << std::endl
<< "modify document assembly: " << "modify document assembly: "
<< show_bool(pdf.allowModifyAssembly()) << std::endl << show_bool(pdf.allowModifyAssembly()) << std::endl
<< "modify forms: " << "modify forms: "
<< show_bool(pdf.allowModifyForm()) << std::endl << show_bool(pdf.allowModifyForm()) << std::endl
<< "modify annotations: " << "modify annotations: "
<< show_bool(pdf.allowModifyAnnotation()) << std::endl << show_bool(pdf.allowModifyAnnotation()) << std::endl
<< "modify other: " << "modify other: "
<< show_bool(pdf.allowModifyOther()) << std::endl << show_bool(pdf.allowModifyOther()) << std::endl
<< "modify anything: " << "modify anything: "
<< show_bool(pdf.allowModifyAll()) << std::endl; << show_bool(pdf.allowModifyAll()) << std::endl;
if (V >= 4) if (V >= 4)
{ {
std::cout << "stream encryption method: " cout << "stream encryption method: "
<< show_encryption_method(stream_method) << std::endl << show_encryption_method(stream_method) << std::endl
<< "string encryption method: " << "string encryption method: "
<< show_encryption_method(string_method) << std::endl << show_encryption_method(string_method) << std::endl
<< "file encryption method: " << "file encryption method: "
<< show_encryption_method(file_method) << std::endl; << show_encryption_method(file_method) << std::endl;
} }
} }
} }
@ -409,21 +411,21 @@ QPDFJob::doCheck(QPDF& pdf)
// errors. // errors.
bool okay = true; bool okay = true;
bool warnings = false; bool warnings = false;
std::cout << "checking " << o.infilename << std::endl; auto& cout = *this->m->cout;
cout << "checking " << o.infilename << std::endl;
try try
{ {
int extension_level = pdf.getExtensionLevel(); int extension_level = pdf.getExtensionLevel();
std::cout << "PDF Version: " << pdf.getPDFVersion(); cout << "PDF Version: " << pdf.getPDFVersion();
if (extension_level > 0) if (extension_level > 0)
{ {
std::cout << " extension level " cout << " extension level " << pdf.getExtensionLevel();
<< pdf.getExtensionLevel();
} }
std::cout << std::endl; cout << std::endl;
showEncryption(pdf); showEncryption(pdf);
if (pdf.isLinearized()) if (pdf.isLinearized())
{ {
std::cout << "File is linearized\n"; cout << "File is linearized\n";
// any errors or warnings are reported by // any errors or warnings are reported by
// checkLinearization(). We treat all issues reported here // checkLinearization(). We treat all issues reported here
// as warnings. // as warnings.
@ -434,7 +436,7 @@ QPDFJob::doCheck(QPDF& pdf)
} }
else else
{ {
std::cout << "File is not linearized\n"; cout << "File is not linearized\n";
} }
// Write the file no nowhere, uncompressing // Write the file no nowhere, uncompressing
@ -464,7 +466,7 @@ QPDFJob::doCheck(QPDF& pdf)
catch (QPDFExc& e) catch (QPDFExc& e)
{ {
okay = false; okay = false;
*(this->m->err_stream) *(this->m->cerr)
<< "ERROR: page " << pageno << ": " << "ERROR: page " << pageno << ": "
<< e.what() << std::endl; << e.what() << std::endl;
} }
@ -472,7 +474,7 @@ QPDFJob::doCheck(QPDF& pdf)
} }
catch (std::exception& e) catch (std::exception& e)
{ {
std::cerr << "ERROR: " << e.what() << std::endl; (*this->m->cerr) << "ERROR: " << e.what() << std::endl;
okay = false; okay = false;
} }
if (! okay) if (! okay)
@ -486,7 +488,7 @@ QPDFJob::doCheck(QPDF& pdf)
} }
else else
{ {
*(this->m->out_stream) *(this->m->cout)
<< "No syntax or stream encoding errors" << "No syntax or stream encoding errors"
<< " found; the file may still contain" << " found; the file may still contain"
<< std::endl << std::endl
@ -495,8 +497,10 @@ QPDFJob::doCheck(QPDF& pdf)
} }
} }
static void do_show_obj(QPDF& pdf, QPDFJob& o) void
QPDFJob::doShowObj(QPDF& pdf)
{ {
QPDFJob& o = *this; // QXXXQ
QPDFObjectHandle obj; QPDFObjectHandle obj;
if (o.show_trailer) if (o.show_trailer)
{ {
@ -531,14 +535,14 @@ static void do_show_obj(QPDF& pdf, QPDFJob& o)
} }
else else
{ {
std::cout *(this->m->cout)
<< "Object is stream. Dictionary:" << std::endl << "Object is stream. Dictionary:" << std::endl
<< obj.getDict().unparseResolved() << std::endl; << obj.getDict().unparseResolved() << std::endl;
} }
} }
else else
{ {
std::cout << obj.unparseResolved() << std::endl; *(this->m->cout) << obj.unparseResolved() << std::endl;
} }
if (error) if (error)
{ {
@ -547,11 +551,14 @@ static void do_show_obj(QPDF& pdf, QPDFJob& o)
} }
} }
static void do_show_pages(QPDF& pdf, QPDFJob& o) void
QPDFJob::doShowPages(QPDF& pdf)
{ {
QPDFJob& o = *this; // QXXXQ
QPDFPageDocumentHelper dh(pdf); QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages(); std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
int pageno = 0; int pageno = 0;
auto& cout = *this->m->cout;
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin(); for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
iter != pages.end(); ++iter) iter != pages.end(); ++iter)
{ {
@ -559,15 +566,15 @@ static void do_show_pages(QPDF& pdf, QPDFJob& o)
QPDFObjectHandle page = ph.getObjectHandle(); QPDFObjectHandle page = ph.getObjectHandle();
++pageno; ++pageno;
std::cout << "page " << pageno << ": " cout << "page " << pageno << ": "
<< page.getObjectID() << " " << page.getObjectID() << " "
<< page.getGeneration() << " R" << std::endl; << page.getGeneration() << " R" << std::endl;
if (o.show_page_images) if (o.show_page_images)
{ {
std::map<std::string, QPDFObjectHandle> images = ph.getImages(); std::map<std::string, QPDFObjectHandle> images = ph.getImages();
if (! images.empty()) if (! images.empty())
{ {
std::cout << " images:" << std::endl; cout << " images:" << std::endl;
for (auto const& iter2: images) for (auto const& iter2: images)
{ {
std::string const& name = iter2.first; std::string const& name = iter2.first;
@ -577,26 +584,28 @@ static void do_show_pages(QPDF& pdf, QPDFJob& o)
dict.getKey("/Width").getIntValueAsInt(); dict.getKey("/Width").getIntValueAsInt();
int height = int height =
dict.getKey("/Height").getIntValueAsInt(); dict.getKey("/Height").getIntValueAsInt();
std::cout << " " << name << ": " cout << " " << name << ": "
<< image.unparse() << image.unparse()
<< ", " << width << " x " << height << ", " << width << " x " << height
<< std::endl; << std::endl;
} }
} }
} }
std::cout << " content:" << std::endl; cout << " content:" << std::endl;
std::vector<QPDFObjectHandle> content = std::vector<QPDFObjectHandle> content =
ph.getPageContents(); ph.getPageContents();
for (auto& iter2: content) for (auto& iter2: content)
{ {
std::cout << " " << iter2.unparse() << std::endl; cout << " " << iter2.unparse() << std::endl;
} }
} }
} }
static void do_list_attachments(QPDF& pdf, QPDFJob& o) void
QPDFJob::doListAttachments(QPDF& pdf)
{ {
QPDFJob& o = *this; // QXXXQ
QPDFEmbeddedFileDocumentHelper efdh(pdf); QPDFEmbeddedFileDocumentHelper efdh(pdf);
if (efdh.hasEmbeddedFiles()) if (efdh.hasEmbeddedFiles())
{ {
@ -604,10 +613,11 @@ static void do_list_attachments(QPDF& pdf, QPDFJob& o)
{ {
std::string const& key = i.first; std::string const& key = i.first;
auto efoh = i.second; auto efoh = i.second;
std::cout << key << " -> " *(this->m->cout)
<< efoh->getEmbeddedFileStream().getObjGen() << key << " -> "
<< std::endl; << efoh->getEmbeddedFileStream().getObjGen()
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { << std::endl;
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
auto desc = efoh->getDescription(); auto desc = efoh->getDescription();
if (! desc.empty()) if (! desc.empty())
{ {
@ -633,7 +643,8 @@ static void do_list_attachments(QPDF& pdf, QPDFJob& o)
} }
else else
{ {
std::cout << o.infilename << " has no embedded files" << std::endl; *(this->m->cout)
<< o.infilename << " has no embedded files" << std::endl;
} }
} }
@ -1554,7 +1565,7 @@ QPDFJob::doJSON(QPDF& pdf)
std::list<std::string> errors; std::list<std::string> errors;
if (! j.checkSchema(schema, errors)) if (! j.checkSchema(schema, errors))
{ {
*(this->m->err_stream) *(this->m->cerr)
<< "QPDFJob didn't create JSON that complies with its own rules.\n\ << "QPDFJob didn't create JSON that complies with its own rules.\n\
Please report this as a bug at\n\ Please report this as a bug at\n\
https://github.com/qpdf/qpdf/issues/new\n\ https://github.com/qpdf/qpdf/issues/new\n\
@ -1563,11 +1574,11 @@ ideally with the file that caused the error and the output below. Thanks!\n\
for (std::list<std::string>::iterator iter = errors.begin(); for (std::list<std::string>::iterator iter = errors.begin();
iter != errors.end(); ++iter) iter != errors.end(); ++iter)
{ {
std::cerr << (*iter) << std::endl; *(this->m->cerr) << (*iter) << std::endl;
} }
} }
std::cout << j.unparse() << std::endl; *(this->m->cout) << j.unparse() << std::endl;
} }
void void
@ -1585,7 +1596,7 @@ QPDFJob::doInspection(QPDF& pdf)
if (o.show_npages) if (o.show_npages)
{ {
QTC::TC("qpdf", "qpdf npages"); QTC::TC("qpdf", "qpdf npages");
std::cout << pdf.getRoot().getKey("/Pages"). *(this->m->cout) << pdf.getRoot().getKey("/Pages").
getKey("/Count").getIntValue() << std::endl; getKey("/Count").getIntValue() << std::endl;
} }
if (o.show_encryption) if (o.show_encryption)
@ -1596,8 +1607,8 @@ QPDFJob::doInspection(QPDF& pdf)
{ {
if (pdf.checkLinearization()) if (pdf.checkLinearization())
{ {
std::cout << o.infilename << ": no linearization errors" *(this->m->cout)
<< std::endl; << o.infilename << ": no linearization errors" << std::endl;
} }
else else
{ {
@ -1612,8 +1623,8 @@ QPDFJob::doInspection(QPDF& pdf)
} }
else else
{ {
std::cout << o.infilename << " is not linearized" *(this->m->cout)
<< std::endl; << o.infilename << " is not linearized" << std::endl;
} }
} }
if (o.show_xref) if (o.show_xref)
@ -1622,15 +1633,15 @@ QPDFJob::doInspection(QPDF& pdf)
} }
if ((o.show_obj > 0) || o.show_trailer) if ((o.show_obj > 0) || o.show_trailer)
{ {
do_show_obj(pdf, o); doShowObj(pdf);
} }
if (o.show_pages) if (o.show_pages)
{ {
do_show_pages(pdf, o); doShowPages(pdf);
} }
if (o.list_attachments) if (o.list_attachments)
{ {
do_list_attachments(pdf, o); doListAttachments(pdf);
} }
if (! o.attachment_to_show.empty()) if (! o.attachment_to_show.empty())
{ {
@ -1661,8 +1672,8 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
{ {
if (! description.empty()) if (! description.empty())
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": not optimizing because image dictionary" << ": not optimizing because image dictionary"
<< " is missing required keys" << std::endl; << " is missing required keys" << std::endl;
}); });
@ -1675,8 +1686,8 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
QTC::TC("qpdf", "qpdf image optimize bits per component"); QTC::TC("qpdf", "qpdf image optimize bits per component");
if (! description.empty()) if (! description.empty())
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": not optimizing because image has other than" << ": not optimizing because image has other than"
<< " 8 bits per component" << std::endl; << " 8 bits per component" << std::endl;
}); });
@ -1728,8 +1739,8 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
QTC::TC("qpdf", "qpdf image optimize colorspace"); QTC::TC("qpdf", "qpdf image optimize colorspace");
if (! description.empty()) if (! description.empty())
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": not optimizing because qpdf can't optimize" << ": not optimizing because qpdf can't optimize"
<< " images with this colorspace" << std::endl; << " images with this colorspace" << std::endl;
}); });
@ -1743,8 +1754,8 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
QTC::TC("qpdf", "qpdf image optimize too small"); QTC::TC("qpdf", "qpdf image optimize too small");
if (! description.empty()) if (! description.empty())
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": not optimizing because image" << ": not optimizing because image"
<< " is smaller than requested minimum dimensions" << " is smaller than requested minimum dimensions"
<< std::endl; << std::endl;
@ -1763,8 +1774,8 @@ ImageOptimizer::evaluate(std::string const& description)
if (! image.pipeStreamData(0, 0, qpdf_dl_specialized, true)) if (! image.pipeStreamData(0, 0, qpdf_dl_specialized, true))
{ {
QTC::TC("qpdf", "qpdf image optimize no pipeline"); QTC::TC("qpdf", "qpdf image optimize no pipeline");
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": not optimizing because unable to decode data" << ": not optimizing because unable to decode data"
<< " or data already uses DCT" << " or data already uses DCT"
<< std::endl; << std::endl;
@ -1787,15 +1798,15 @@ ImageOptimizer::evaluate(std::string const& description)
if (c.getCount() >= orig_length) if (c.getCount() >= orig_length)
{ {
QTC::TC("qpdf", "qpdf image optimize no shrink"); QTC::TC("qpdf", "qpdf image optimize no shrink");
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": not optimizing because DCT compression does not" << ": not optimizing because DCT compression does not"
<< " reduce image size" << std::endl; << " reduce image size" << std::endl;
}); });
return false; return false;
} }
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << description cout << prefix << ": " << description
<< ": optimizing image reduces size from " << ": optimizing image reduces size from "
<< orig_length << " to " << c.getCount() << orig_length << " to " << c.getCount()
<< std::endl; << std::endl;
@ -1919,8 +1930,8 @@ static PointerHolder<QPDF> do_process(
if (! warned) if (! warned)
{ {
warned = true; warned = true;
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": supplied password didn't work;" cout << prefix << ": supplied password didn't work;"
<< " trying other passwords based on interpreting" << " trying other passwords based on interpreting"
<< " password with different string encodings" << " password with different string encodings"
<< std::endl; << std::endl;
@ -2061,7 +2072,7 @@ static void do_under_overlay_for_page(
iter != pagenos[pageno].end(); ++iter) iter != pagenos[pageno].end(); ++iter)
{ {
int from_pageno = *iter; int from_pageno = *iter;
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << " " << uo.which << " " << from_pageno << std::endl; cout << " " << uo.which << " " << from_pageno << std::endl;
}); });
auto from_page = pages.at(QIntC::to_size(from_pageno - 1)); auto from_page = pages.at(QIntC::to_size(from_pageno - 1));
@ -2144,12 +2155,12 @@ QPDFJob::handleUnderOverlay(QPDF& pdf)
QPDFPageDocumentHelper main_pdh(pdf); QPDFPageDocumentHelper main_pdh(pdf);
std::vector<QPDFPageObjectHelper> main_pages = main_pdh.getAllPages(); std::vector<QPDFPageObjectHelper> main_pages = main_pdh.getAllPages();
size_t main_npages = main_pages.size(); size_t main_npages = main_pages.size();
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": processing underlay/overlay" << std::endl; cout << prefix << ": processing underlay/overlay" << std::endl;
}); });
for (size_t i = 0; i < main_npages; ++i) for (size_t i = 0; i < main_npages; ++i)
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << " page " << 1+i << std::endl; cout << " page " << 1+i << std::endl;
}); });
do_under_overlay_for_page(pdf, o, o.underlay, underlay_pagenos, i, do_under_overlay_for_page(pdf, o, o.underlay, underlay_pagenos, i,
@ -2200,8 +2211,8 @@ QPDFJob::addAttachments(QPDF& pdf)
} }
efdh.replaceEmbeddedFile(to_add.key, fs); efdh.replaceEmbeddedFile(to_add.key, fs);
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": attached " << to_add.path cout << prefix << ": attached " << to_add.path
<< " as " << to_add.filename << " as " << to_add.filename
<< " with key " << to_add.key << std::endl; << " with key " << to_add.key << std::endl;
}); });
@ -2235,8 +2246,8 @@ QPDFJob::copyAttachments(QPDF& pdf)
std::vector<std::string> duplicates; std::vector<std::string> duplicates;
for (auto const& to_copy: o.attachments_to_copy) for (auto const& to_copy: o.attachments_to_copy)
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": copying attachments from " cout << prefix << ": copying attachments from "
<< to_copy.path << std::endl; << to_copy.path << std::endl;
}); });
auto other = processFile( auto other = processFile(
@ -2258,7 +2269,7 @@ QPDFJob::copyAttachments(QPDF& pdf)
efdh.replaceEmbeddedFile( efdh.replaceEmbeddedFile(
new_key, QPDFFileSpecObjectHelper(new_fs_oh)); new_key, QPDFFileSpecObjectHelper(new_fs_oh));
o.doIfVerbose([&](std::ostream& cout, o.doIfVerbose([&](std::ostream& cout,
std::string const& whoami) { std::string const& prefix) {
cout << " " << iter.first << " -> " << new_key cout << " " << iter.first << " -> " << new_key
<< std::endl; << std::endl;
}); });
@ -2386,8 +2397,8 @@ QPDFJob::handleTransformations(QPDF& pdf)
if (efdh.removeEmbeddedFile(key)) if (efdh.removeEmbeddedFile(key))
{ {
o.doIfVerbose([&](std::ostream& cout, o.doIfVerbose([&](std::ostream& cout,
std::string const& whoami) { std::string const& prefix) {
cout << whoami << cout << prefix <<
": removed attachment " << key << std::endl; ": removed attachment " << key << std::endl;
}); });
} }
@ -2431,8 +2442,8 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
std::set<QPDFObjGen> resources_seen; // shared resources detection std::set<QPDFObjGen> resources_seen; // shared resources detection
std::set<QPDFObjGen> nodes_seen; // loop detection std::set<QPDFObjGen> nodes_seen; // loop detection
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": " << pdf.getFilename() cout << prefix << ": " << pdf.getFilename()
<< ": checking for shared resources" << std::endl; << ": checking for shared resources" << std::endl;
}); });
@ -2457,7 +2468,7 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
{ {
QTC::TC("qpdf", "qpdf found resources in non-leaf"); QTC::TC("qpdf", "qpdf found resources in non-leaf");
o.doIfVerbose([&](std::ostream& cout, o.doIfVerbose([&](std::ostream& cout,
std::string const& whoami) { std::string const& prefix) {
cout << " found resources in non-leaf page node " cout << " found resources in non-leaf page node "
<< og.getObj() << " " << og.getGen() << og.getObj() << " " << og.getGen()
<< std::endl; << std::endl;
@ -2481,7 +2492,7 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
{ {
QTC::TC("qpdf", "qpdf found shared resources in leaf"); QTC::TC("qpdf", "qpdf found shared resources in leaf");
o.doIfVerbose([&](std::ostream& cout, o.doIfVerbose([&](std::ostream& cout,
std::string const& whoami) { std::string const& prefix) {
cout << " found shared resources in leaf node " cout << " found shared resources in leaf node "
<< og.getObj() << " " << og.getGen() << og.getObj() << " " << og.getGen()
<< ": " << ": "
@ -2503,7 +2514,7 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
{ {
QTC::TC("qpdf", "qpdf found shared xobject in leaf"); QTC::TC("qpdf", "qpdf found shared xobject in leaf");
o.doIfVerbose([&](std::ostream& cout, o.doIfVerbose([&](std::ostream& cout,
std::string const& whoami) { std::string const& prefix) {
cout << " found shared xobject in leaf node " cout << " found shared xobject in leaf node "
<< og.getObj() << " " << og.getGen() << og.getObj() << " " << og.getGen()
<< ": " << ": "
@ -2535,8 +2546,8 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
} }
} }
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": no shared resources found" << std::endl; cout << prefix << ": no shared resources found" << std::endl;
}); });
return false; return false;
} }
@ -2583,25 +2594,23 @@ static void handle_page_specs(
// some portable heuristic based on OS limits, just hard-code // some portable heuristic based on OS limits, just hard-code
// this at a given number and allow users to override. // this at a given number and allow users to override.
std::set<std::string> filenames; std::set<std::string> filenames;
for (std::vector<QPDFJob::PageSpec>::iterator iter = o.page_specs.begin(); for (auto& page_spec: o.page_specs)
iter != o.page_specs.end(); ++iter)
{ {
QPDFJob::PageSpec& page_spec = *iter;
filenames.insert(page_spec.filename); filenames.insert(page_spec.filename);
} }
if (filenames.size() > o.keep_files_open_threshold) if (filenames.size() > o.keep_files_open_threshold)
{ {
QTC::TC("qpdf", "qpdf disable keep files open"); QTC::TC("qpdf", "qpdf disable keep files open");
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": selecting --keep-open-files=n" cout << prefix << ": selecting --keep-open-files=n"
<< std::endl; << std::endl;
}); });
o.keep_files_open = false; o.keep_files_open = false;
} }
else else
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": selecting --keep-open-files=y" cout << prefix << ": selecting --keep-open-files=y"
<< std::endl; << std::endl;
}); });
o.keep_files_open = true; o.keep_files_open = true;
@ -2638,8 +2647,8 @@ static void handle_page_specs(
QTC::TC("qpdf", "qpdf pages encryption password"); QTC::TC("qpdf", "qpdf pages encryption password");
password = o.encryption_file_password; password = o.encryption_file_password;
} }
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": processing " cout << prefix << ": processing "
<< page_spec.filename << std::endl; << page_spec.filename << std::endl;
}); });
PointerHolder<InputSource> is; PointerHolder<InputSource> is;
@ -2709,8 +2718,8 @@ static void handle_page_specs(
// without changing their object numbers. This enables other // without changing their object numbers. This enables other
// things in the original file, such as outlines, to continue to // things in the original file, such as outlines, to continue to
// work. // work.
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami cout << prefix
<< ": removing unreferenced pages from primary input" << ": removing unreferenced pages from primary input"
<< std::endl; << std::endl;
}); });
@ -2783,8 +2792,8 @@ static void handle_page_specs(
{ {
any_page_labels = true; any_page_labels = true;
} }
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": adding pages from " cout << prefix << ": adding pages from "
<< page_data.filename << std::endl; << page_data.filename << std::endl;
}); });
for (std::vector<int>::iterator pageno_iter = for (std::vector<int>::iterator pageno_iter =
@ -2963,8 +2972,10 @@ static void handle_rotations(QPDF& pdf, QPDFJob& o)
} }
} }
static void maybe_fix_write_password(int R, QPDFJob& o, std::string& password) void
QPDFJob::maybeFixWritePassword(int R, std::string& password)
{ {
QPDFJob& o = *this; // QXXXQ
switch (o.password_mode) switch (o.password_mode)
{ {
case QPDFJob::pm_bytes: case QPDFJob::pm_bytes:
@ -3020,9 +3031,9 @@ static void maybe_fix_write_password(int R, QPDFJob& o, std::string& password)
{ {
QTC::TC("qpdf", "qpdf auto-encode password"); QTC::TC("qpdf", "qpdf auto-encode password");
o.doIfVerbose([&](std::ostream& cout, o.doIfVerbose([&](std::ostream& cout,
std::string const& whoami) { std::string const& prefix) {
cout cout
<< whoami << prefix
<< ": automatically converting Unicode" << ": automatically converting Unicode"
<< " password to single-byte encoding as" << " password to single-byte encoding as"
<< " required for 40-bit or 128-bit" << " required for 40-bit or 128-bit"
@ -3033,8 +3044,8 @@ static void maybe_fix_write_password(int R, QPDFJob& o, std::string& password)
else else
{ {
QTC::TC("qpdf", "qpdf bytes fallback warning"); QTC::TC("qpdf", "qpdf bytes fallback warning");
std::cerr *(this->m->cerr)
<< whoami << ": WARNING: " << this->m->message_prefix << ": WARNING: "
<< "supplied password looks like a Unicode" << "supplied password looks like a Unicode"
<< " password with characters not allowed in" << " password with characters not allowed in"
<< " passwords for 40-bit and 128-bit encryption;" << " passwords for 40-bit and 128-bit encryption;"
@ -3060,8 +3071,10 @@ static void maybe_fix_write_password(int R, QPDFJob& o, std::string& password)
} }
} }
static void set_encryption_options(QPDF& pdf, QPDFJob& o, QPDFWriter& w) void
QPDFJob::setEncryptionOptions(QPDF& pdf, QPDFWriter& w)
{ {
QPDFJob& o = *this; // QXXXQ
int R = 0; int R = 0;
if (o.keylen == 40) if (o.keylen == 40)
{ {
@ -3095,12 +3108,13 @@ static void set_encryption_options(QPDF& pdf, QPDFJob& o, QPDFWriter& w)
} }
if ((R > 3) && (o.r3_accessibility == false)) if ((R > 3) && (o.r3_accessibility == false))
{ {
std::cerr << whoami *(this->m->cerr)
<< ": -accessibility=n is ignored for modern" << this->m->message_prefix
<< " encryption formats" << std::endl; << ": -accessibility=n is ignored for modern"
<< " encryption formats" << std::endl;
} }
maybe_fix_write_password(R, o, o.user_password); maybeFixWritePassword(R, o.user_password);
maybe_fix_write_password(R, o, o.owner_password); maybeFixWritePassword(R, o.owner_password);
if ((R < 4) || ((R == 4) && (! o.use_aes))) if ((R < 4) || ((R == 4) && (! o.use_aes)))
{ {
if (! o.allow_weak_crypto) if (! o.allow_weak_crypto)
@ -3108,8 +3122,8 @@ static void set_encryption_options(QPDF& pdf, QPDFJob& o, QPDFWriter& w)
// Do not set warnings = true for this case as this does // Do not set warnings = true for this case as this does
// not reflect a potential problem with the input file. // not reflect a potential problem with the input file.
QTC::TC("qpdf", "qpdf weak crypto warning"); QTC::TC("qpdf", "qpdf weak crypto warning");
std::cerr *(this->m->cerr)
<< whoami << this->m->message_prefix
<< ": writing a file with RC4, a weak cryptographic algorithm" << ": writing a file with RC4, a weak cryptographic algorithm"
<< std::endl << std::endl
<< "Please use 256-bit keys for better security." << "Please use 256-bit keys for better security."
@ -3233,7 +3247,7 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w)
} }
if (o.encrypt) if (o.encrypt)
{ {
set_encryption_options(pdf, o, w); setEncryptionOptions(pdf, w);
} }
if (o.linearize) if (o.linearize)
{ {
@ -3264,7 +3278,8 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w)
if (o.progress && o.outfilename) if (o.progress && o.outfilename)
{ {
w.registerProgressReporter( w.registerProgressReporter(
new ProgressReporter(this->m->whoami, o.outfilename)); new ProgressReporter(
*(this->m->cout), this->m->message_prefix, o.outfilename));
} }
} }
@ -3378,8 +3393,8 @@ QPDFJob::doSplitPages(QPDF& pdf, bool& warnings)
QPDFWriter w(outpdf, outfile.c_str()); QPDFWriter w(outpdf, outfile.c_str());
setWriterOptions(outpdf, w); setWriterOptions(outpdf, w);
w.write(); w.write();
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": wrote file " << outfile << std::endl; cout << prefix << ": wrote file " << outfile << std::endl;
}); });
if (outpdf.anyWarnings()) if (outpdf.anyWarnings())
{ {
@ -3415,8 +3430,8 @@ QPDFJob::writeOutfile(QPDF& pdf)
} }
if (o.outfilename) if (o.outfilename)
{ {
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) { o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
cout << whoami << ": wrote file " << o.outfilename << std::endl; cout << prefix << ": wrote file " << o.outfilename << std::endl;
}); });
} }
if (o.replace_input) if (o.replace_input)
@ -3437,9 +3452,10 @@ QPDFJob::writeOutfile(QPDF& pdf)
QUtil::rename_file(temp_out.c_str(), o.infilename); QUtil::rename_file(temp_out.c_str(), o.infilename);
if (warnings) if (warnings)
{ {
std::cerr << whoami *(this->m->cerr)
<< ": there are warnings; original file kept in " << this->m->message_prefix
<< backup << std::endl; << ": there are warnings; original file kept in "
<< backup << std::endl;
} }
else else
{ {
@ -3449,8 +3465,8 @@ QPDFJob::writeOutfile(QPDF& pdf)
} }
catch (QPDFSystemError& e) catch (QPDFSystemError& e)
{ {
std::cerr *(this->m->cerr)
<< whoami << this->m->message_prefix
<< ": unable to delete original file (" << ": unable to delete original file ("
<< e.what() << ");" << e.what() << ");"
<< " original file left in " << backup << " original file left in " << backup