mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
QPDF, QPDFJob: use QPDFLogger instead of custom output streams
This commit is contained in:
parent
f1f711963b
commit
641e92c6a7
@ -1,5 +1,9 @@
|
|||||||
2022-06-05 Jay Berkenbilt <ejb@ql.org>
|
2022-06-05 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* QPDFJob: API breaking change: QPDFJob::doIfVerbose passes a
|
||||||
|
Pipeline& rather than a std::ostream& to the the callback
|
||||||
|
function.
|
||||||
|
|
||||||
* Add integer types to pipeline's operator<<: short, int, long,
|
* Add integer types to pipeline's operator<<: short, int, long,
|
||||||
long long, unsigned short, unsigned int, unsigned long, unsigned
|
long long, unsigned short, unsigned int, unsigned long, unsigned
|
||||||
long long.
|
long long.
|
||||||
|
@ -512,6 +512,28 @@ to the owner of the parent directory source tree.
|
|||||||
Note: this will leave some extra files (like .bash_history) in the
|
Note: this will leave some extra files (like .bash_history) in the
|
||||||
parent directory of the source tree. You will want to clean those up.
|
parent directory of the source tree. You will want to clean those up.
|
||||||
|
|
||||||
|
DEPRECATION
|
||||||
|
|
||||||
|
This is a reminder of how to use and test deprecation.
|
||||||
|
|
||||||
|
To temporarily disable deprecation warnings for testing:
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
|
// Do deprecated thing here
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
To declare something as deprecated:
|
||||||
|
|
||||||
|
[[deprecated("explanation")]]
|
||||||
|
|
||||||
|
|
||||||
LOCAL WINDOWS TESTING PROCEDURE
|
LOCAL WINDOWS TESTING PROCEDURE
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
class QPDF_Stream;
|
class QPDF_Stream;
|
||||||
class BitStream;
|
class BitStream;
|
||||||
class BitWriter;
|
class BitWriter;
|
||||||
|
class QPDFLogger;
|
||||||
|
|
||||||
class QPDF
|
class QPDF
|
||||||
{
|
{
|
||||||
@ -209,20 +210,30 @@ class QPDF
|
|||||||
|
|
||||||
// Parameter settings
|
// Parameter settings
|
||||||
|
|
||||||
// By default, warning messages are issued to std::cerr and output
|
// To capture or redirect output, configure the logger returned by
|
||||||
// messages printed by certain check calls are issued to
|
// getLogger(). By default, all QPDF and QPDFJob objects share the
|
||||||
// std::cout. This method allows you to specify alternative
|
// global logger. If you need a private logger for some reason,
|
||||||
// streams for this purpose. Note that no normal QPDF operations
|
// pass a new one to setLogger(). See comments in QPDFLogger.hh
|
||||||
// generate output to std::cout, so for applications that just
|
// for details on configuring the logger.
|
||||||
// wish to avoid creating output and don't call any check
|
//
|
||||||
// functions, calling setSuppressWarnings(true) is sufficient.
|
// Note that no normal QPDF operations generate output to standard
|
||||||
// Applications that wish to present check or warning information
|
// output, so for applications that just wish to avoid creating
|
||||||
// to users may replace the output and error streams to capture
|
// output for warnings and don't call any check functions, calling
|
||||||
// the output and errors for other use. A null value for either
|
// setSuppressWarnings(true) is sufficient.
|
||||||
// stream will cause QPDF to use std::cout or std::cerr as
|
|
||||||
// appropriate.
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
std::shared_ptr<QPDFLogger> getLogger();
|
||||||
|
QPDF_DLL
|
||||||
|
void setLogger(std::shared_ptr<QPDFLogger>);
|
||||||
|
|
||||||
|
// This deprecated method is the old way to capture output, but it
|
||||||
|
// didn't capture all output. See comments above for getLogger and
|
||||||
|
// setLogger. This will be removed in QPDF 12. For now, it
|
||||||
|
// configures a private logger, separating this object from the
|
||||||
|
// default logger, and calls setOutputStreams on that logger. See
|
||||||
|
// QPDFLogger.hh for additional details.
|
||||||
|
[[deprecated(
|
||||||
|
"configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
|
||||||
|
setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||||
|
|
||||||
// If true, ignore any cross-reference streams in a hybrid file
|
// If true, ignore any cross-reference streams in a hybrid file
|
||||||
// (one that contains both cross-reference streams and
|
// (one that contains both cross-reference streams and
|
||||||
@ -618,18 +629,17 @@ class QPDF
|
|||||||
|
|
||||||
// Performs various sanity checks on a linearized file. Return
|
// Performs various sanity checks on a linearized file. Return
|
||||||
// true if no errors or warnings. Otherwise, return false and
|
// true if no errors or warnings. Otherwise, return false and
|
||||||
// output errors and warnings to std::cout or the output stream
|
// output errors and warnings to the default output stream
|
||||||
// specified in a call to setOutputStreams. It is recommended for
|
// (std::cout or whatever is configured in the logger). It is
|
||||||
// linearization errors to be treated as warnings.
|
// recommended for linearization errors to be treated as warnings.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool checkLinearization();
|
bool checkLinearization();
|
||||||
|
|
||||||
// Calls checkLinearization() and, if possible, prints normalized
|
// Calls checkLinearization() and, if possible, prints normalized
|
||||||
// contents of some of the hints tables to std::cout or the output
|
// contents of some of the hints tables to the default output
|
||||||
// stream specified in a call to setOutputStreams. Normalization
|
// stream. Normalization includes adding min values to delta
|
||||||
// includes adding min values to delta values and adjusting
|
// values and adjusting offsets based on the location and size of
|
||||||
// offsets based on the location and size of the primary hint
|
// the primary hint stream.
|
||||||
// stream.
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void showLinearizationData();
|
void showLinearizationData();
|
||||||
|
|
||||||
@ -1661,6 +1671,7 @@ class QPDF
|
|||||||
Members();
|
Members();
|
||||||
Members(Members const&) = delete;
|
Members(Members const&) = delete;
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFLogger> log;
|
||||||
unsigned long long unique_id;
|
unsigned long long unique_id;
|
||||||
QPDFTokenizer tokenizer;
|
QPDFTokenizer tokenizer;
|
||||||
std::shared_ptr<InputSource> file;
|
std::shared_ptr<InputSource> file;
|
||||||
@ -1668,8 +1679,6 @@ class QPDF
|
|||||||
bool provided_password_is_hex_key;
|
bool provided_password_is_hex_key;
|
||||||
bool ignore_xref_streams;
|
bool ignore_xref_streams;
|
||||||
bool suppress_warnings;
|
bool suppress_warnings;
|
||||||
std::ostream* out_stream;
|
|
||||||
std::ostream* err_stream;
|
|
||||||
bool attempt_recovery;
|
bool attempt_recovery;
|
||||||
std::shared_ptr<EncryptionParameters> encp;
|
std::shared_ptr<EncryptionParameters> encp;
|
||||||
std::string pdf_version;
|
std::string pdf_version;
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
class QPDFWriter;
|
class QPDFWriter;
|
||||||
class Pipeline;
|
class Pipeline;
|
||||||
|
class QPDFLogger;
|
||||||
|
|
||||||
class QPDFJob
|
class QPDFJob
|
||||||
{
|
{
|
||||||
@ -108,10 +109,28 @@ class QPDFJob
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setMessagePrefix(std::string const&);
|
void setMessagePrefix(std::string const&);
|
||||||
|
|
||||||
// Override streams that errors and output go to. Defaults are
|
// To capture or redirect output, configure the logger returned by
|
||||||
// std::cout and std::cerr. Pass nullptr to use the default.
|
// getLogger(). By default, all QPDF and QPDFJob objects share the
|
||||||
|
// global logger. If you need a private logger for some reason,
|
||||||
|
// pass a new one to setLogger(). See comments in QPDFLogger.hh
|
||||||
|
// for details on configuring the logger.
|
||||||
|
//
|
||||||
|
// If you set a custom logger here, the logger will be passed to
|
||||||
|
// all subsequent QPDF objects created by this QPDFJob object.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
std::shared_ptr<QPDFLogger> getLogger();
|
||||||
|
QPDF_DLL
|
||||||
|
void setLogger(std::shared_ptr<QPDFLogger>);
|
||||||
|
|
||||||
|
// This deprecated method is the old way to capture output, but it
|
||||||
|
// didn't capture all output. See comments above for getLogger and
|
||||||
|
// setLogger. This will be removed in QPDF 12. For now, it
|
||||||
|
// configures a private logger, separating this object from the
|
||||||
|
// default logger, and calls setOutputStreams on that logger. See
|
||||||
|
// QPDFLogger.hh for additional details.
|
||||||
|
[[deprecated(
|
||||||
|
"configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
|
||||||
|
setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||||
|
|
||||||
// Check to make sure no contradictory options have been
|
// Check to make sure no contradictory options have been
|
||||||
// specified. This is called automatically after initializing from
|
// specified. This is called automatically after initializing from
|
||||||
@ -393,8 +412,8 @@ class QPDFJob
|
|||||||
// If in verbose mode, call the given function, passing in the
|
// If in verbose mode, call the given function, passing in the
|
||||||
// output stream and message prefix.
|
// output stream and message prefix.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void doIfVerbose(
|
void
|
||||||
std::function<void(std::ostream&, std::string const& prefix)> fn);
|
doIfVerbose(std::function<void(Pipeline&, std::string const& prefix)> fn);
|
||||||
|
|
||||||
// Provide a string that is the help information ("schema" for the
|
// Provide a string that is the help information ("schema" for the
|
||||||
// qpdf-specific JSON object) for version 1 of the JSON output.
|
// qpdf-specific JSON object) for version 1 of the JSON output.
|
||||||
@ -548,10 +567,9 @@ class QPDFJob
|
|||||||
Members();
|
Members();
|
||||||
Members(Members const&) = delete;
|
Members(Members const&) = delete;
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFLogger> log;
|
||||||
std::string message_prefix;
|
std::string message_prefix;
|
||||||
bool warnings;
|
bool warnings;
|
||||||
std::ostream* cout;
|
|
||||||
std::ostream* cerr;
|
|
||||||
unsigned long encryption_status;
|
unsigned long encryption_status;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
std::shared_ptr<char> password;
|
std::shared_ptr<char> password;
|
||||||
|
@ -18,14 +18,15 @@
|
|||||||
#include <qpdf/OffsetInputSource.hh>
|
#include <qpdf/OffsetInputSource.hh>
|
||||||
#include <qpdf/Pipeline.hh>
|
#include <qpdf/Pipeline.hh>
|
||||||
#include <qpdf/Pl_Discard.hh>
|
#include <qpdf/Pl_Discard.hh>
|
||||||
#include <qpdf/QTC.hh>
|
#include <qpdf/Pl_OStream.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
|
|
||||||
#include <qpdf/QPDFExc.hh>
|
#include <qpdf/QPDFExc.hh>
|
||||||
|
#include <qpdf/QPDFLogger.hh>
|
||||||
#include <qpdf/QPDF_Array.hh>
|
#include <qpdf/QPDF_Array.hh>
|
||||||
#include <qpdf/QPDF_Dictionary.hh>
|
#include <qpdf/QPDF_Dictionary.hh>
|
||||||
#include <qpdf/QPDF_Null.hh>
|
#include <qpdf/QPDF_Null.hh>
|
||||||
#include <qpdf/QPDF_Stream.hh>
|
#include <qpdf/QPDF_Stream.hh>
|
||||||
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
// This must be a fixed value. This API returns a const reference to
|
// This must be a fixed value. This API returns a const reference to
|
||||||
// it, and the C API relies on its being static as well.
|
// it, and the C API relies on its being static as well.
|
||||||
@ -212,13 +213,12 @@ QPDF::EncryptionParameters::EncryptionParameters() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPDF::Members::Members() :
|
QPDF::Members::Members() :
|
||||||
|
log(QPDFLogger::defaultLogger()),
|
||||||
unique_id(0),
|
unique_id(0),
|
||||||
file(new InvalidInputSource()),
|
file(new InvalidInputSource()),
|
||||||
provided_password_is_hex_key(false),
|
provided_password_is_hex_key(false),
|
||||||
ignore_xref_streams(false),
|
ignore_xref_streams(false),
|
||||||
suppress_warnings(false),
|
suppress_warnings(false),
|
||||||
out_stream(&std::cout),
|
|
||||||
err_stream(&std::cerr),
|
|
||||||
attempt_recovery(true),
|
attempt_recovery(true),
|
||||||
encp(new EncryptionParameters),
|
encp(new EncryptionParameters),
|
||||||
pushed_inherited_attributes_to_pages(false),
|
pushed_inherited_attributes_to_pages(false),
|
||||||
@ -339,11 +339,23 @@ QPDF::setIgnoreXRefStreams(bool val)
|
|||||||
this->m->ignore_xref_streams = val;
|
this->m->ignore_xref_streams = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFLogger>
|
||||||
|
QPDF::getLogger()
|
||||||
|
{
|
||||||
|
return this->m->log;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDF::setLogger(std::shared_ptr<QPDFLogger> l)
|
||||||
|
{
|
||||||
|
this->m->log = l;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::setOutputStreams(std::ostream* out, std::ostream* err)
|
QPDF::setOutputStreams(std::ostream* out, std::ostream* err)
|
||||||
{
|
{
|
||||||
this->m->out_stream = out ? out : &std::cout;
|
setLogger(std::make_shared<QPDFLogger>());
|
||||||
this->m->err_stream = err ? err : &std::cerr;
|
this->m->log->setOutputStreams(out, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -533,8 +545,8 @@ QPDF::warn(QPDFExc const& e)
|
|||||||
{
|
{
|
||||||
this->m->warnings.push_back(e);
|
this->m->warnings.push_back(e);
|
||||||
if (!this->m->suppress_warnings) {
|
if (!this->m->suppress_warnings) {
|
||||||
*this->m->err_stream << "WARNING: " << this->m->warnings.back().what()
|
*this->m->log->getWarn()
|
||||||
<< std::endl;
|
<< "WARNING: " << this->m->warnings.back().what() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1345,18 +1357,18 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
|
|||||||
void
|
void
|
||||||
QPDF::showXRefTable()
|
QPDF::showXRefTable()
|
||||||
{
|
{
|
||||||
|
auto& cout = *this->m->log->getInfo();
|
||||||
for (auto const& iter: this->m->xref_table) {
|
for (auto const& iter: this->m->xref_table) {
|
||||||
QPDFObjGen const& og = iter.first;
|
QPDFObjGen const& og = iter.first;
|
||||||
QPDFXRefEntry const& entry = iter.second;
|
QPDFXRefEntry const& entry = iter.second;
|
||||||
*this->m->out_stream << og.getObj() << "/" << og.getGen() << ": ";
|
cout << og.getObj() << "/" << og.getGen() << ": ";
|
||||||
switch (entry.getType()) {
|
switch (entry.getType()) {
|
||||||
case 1:
|
case 1:
|
||||||
*this->m->out_stream << "uncompressed; offset = "
|
cout << "uncompressed; offset = " << entry.getOffset();
|
||||||
<< entry.getOffset();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
*this->m->out_stream
|
*this->m->log->getInfo()
|
||||||
<< "compressed; stream = " << entry.getObjStreamNumber()
|
<< "compressed; stream = " << entry.getObjStreamNumber()
|
||||||
<< ", index = " << entry.getObjStreamIndex();
|
<< ", index = " << entry.getObjStreamIndex();
|
||||||
break;
|
break;
|
||||||
@ -1366,7 +1378,7 @@ QPDF::showXRefTable()
|
|||||||
" showing xref_table");
|
" showing xref_table");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*this->m->out_stream << std::endl;
|
this->m->log->info("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
#include <qpdf/Pl_OStream.hh>
|
#include <qpdf/Pl_OStream.hh>
|
||||||
#include <qpdf/Pl_StdioFile.hh>
|
#include <qpdf/Pl_StdioFile.hh>
|
||||||
#include <qpdf/Pl_String.hh>
|
#include <qpdf/Pl_String.hh>
|
||||||
#include <qpdf/QTC.hh>
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||||
@ -27,6 +24,7 @@
|
|||||||
#include <qpdf/QPDFCryptoProvider.hh>
|
#include <qpdf/QPDFCryptoProvider.hh>
|
||||||
#include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
|
#include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFExc.hh>
|
#include <qpdf/QPDFExc.hh>
|
||||||
|
#include <qpdf/QPDFLogger.hh>
|
||||||
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageLabelDocumentHelper.hh>
|
#include <qpdf/QPDFPageLabelDocumentHelper.hh>
|
||||||
@ -34,6 +32,8 @@
|
|||||||
#include <qpdf/QPDFSystemError.hh>
|
#include <qpdf/QPDFSystemError.hh>
|
||||||
#include <qpdf/QPDFUsage.hh>
|
#include <qpdf/QPDFUsage.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
#include <qpdf/auto_job_schema.hh> // JOB_SCHEMA_DATA
|
#include <qpdf/auto_job_schema.hh> // JOB_SCHEMA_DATA
|
||||||
|
|
||||||
@ -93,10 +93,8 @@ namespace
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProgressReporter(
|
ProgressReporter(
|
||||||
std::ostream& cout,
|
Pipeline& p, std::string const& prefix, char const* filename) :
|
||||||
std::string const& prefix,
|
p(p),
|
||||||
char const* filename) :
|
|
||||||
cout(cout),
|
|
||||||
prefix(prefix),
|
prefix(prefix),
|
||||||
filename(filename)
|
filename(filename)
|
||||||
{
|
{
|
||||||
@ -105,7 +103,7 @@ namespace
|
|||||||
virtual void reportProgress(int);
|
virtual void reportProgress(int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream& cout;
|
Pipeline& p;
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
};
|
};
|
||||||
@ -135,10 +133,10 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
|
|||||||
QPDFObjectHandle colorspace_obj = dict.getKey("/ColorSpace");
|
QPDFObjectHandle colorspace_obj = dict.getKey("/ColorSpace");
|
||||||
if (!(w_obj.isNumber() && h_obj.isNumber())) {
|
if (!(w_obj.isNumber() && h_obj.isNumber())) {
|
||||||
if (!description.empty()) {
|
if (!description.empty()) {
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << prefix << ": " << description
|
||||||
<< ": not optimizing because image dictionary"
|
<< ": not optimizing because image dictionary"
|
||||||
<< " is missing required keys" << std::endl;
|
<< " is missing required keys\n";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -147,10 +145,10 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
|
|||||||
if (!(components_obj.isInteger() && (components_obj.getIntValue() == 8))) {
|
if (!(components_obj.isInteger() && (components_obj.getIntValue() == 8))) {
|
||||||
QTC::TC("qpdf", "QPDFJob image optimize bits per component");
|
QTC::TC("qpdf", "QPDFJob image optimize bits per component");
|
||||||
if (!description.empty()) {
|
if (!description.empty()) {
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << 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\n";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -185,10 +183,10 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
|
|||||||
} else {
|
} else {
|
||||||
QTC::TC("qpdf", "QPDFJob image optimize colorspace");
|
QTC::TC("qpdf", "QPDFJob image optimize colorspace");
|
||||||
if (!description.empty()) {
|
if (!description.empty()) {
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << 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\n";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -198,11 +196,10 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
|
|||||||
((this->oi_min_area > 0) && ((w * h) <= this->oi_min_area))) {
|
((this->oi_min_area > 0) && ((w * h) <= this->oi_min_area))) {
|
||||||
QTC::TC("qpdf", "QPDFJob image optimize too small");
|
QTC::TC("qpdf", "QPDFJob image optimize too small");
|
||||||
if (!description.empty()) {
|
if (!description.empty()) {
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << prefix << ": " << description
|
||||||
<< ": not optimizing because image"
|
<< ": not optimizing because image"
|
||||||
<< " is smaller than requested minimum dimensions"
|
<< " is smaller than requested minimum dimensions\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -217,10 +214,10 @@ 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", "QPDFJob image optimize no pipeline");
|
QTC::TC("qpdf", "QPDFJob image optimize no pipeline");
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << prefix << ": " << description
|
||||||
<< ": not optimizing because unable to decode data"
|
<< ": not optimizing because unable to decode data"
|
||||||
<< " or data already uses DCT" << std::endl;
|
<< " or data already uses DCT\n";
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -237,17 +234,17 @@ ImageOptimizer::evaluate(std::string const& description)
|
|||||||
long long orig_length = image.getDict().getKey("/Length").getIntValue();
|
long long orig_length = image.getDict().getKey("/Length").getIntValue();
|
||||||
if (c.getCount() >= orig_length) {
|
if (c.getCount() >= orig_length) {
|
||||||
QTC::TC("qpdf", "QPDFJob image optimize no shrink");
|
QTC::TC("qpdf", "QPDFJob image optimize no shrink");
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << prefix << ": " << description
|
||||||
<< ": not optimizing because DCT compression does not"
|
<< ": not optimizing because DCT compression does not"
|
||||||
<< " reduce image size" << std::endl;
|
<< " reduce image size\n";
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
o.doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << description
|
v << prefix << ": " << description
|
||||||
<< ": optimizing image reduces size from " << orig_length << " to "
|
<< ": optimizing image reduces size from " << orig_length << " to "
|
||||||
<< c.getCount() << std::endl;
|
<< c.getCount() << "\n";
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -304,8 +301,8 @@ QPDFPageData::QPDFPageData(QPDFPageData const& other, int page) :
|
|||||||
void
|
void
|
||||||
ProgressReporter::reportProgress(int percentage)
|
ProgressReporter::reportProgress(int percentage)
|
||||||
{
|
{
|
||||||
this->cout << prefix << ": " << filename
|
this->p << prefix << ": " << filename << ": write progress: " << percentage
|
||||||
<< ": write progress: " << percentage << "%" << std::endl;
|
<< "%\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// These default values are duplicated in help and docs.
|
// These default values are duplicated in help and docs.
|
||||||
@ -316,10 +313,9 @@ static int constexpr DEFAULT_OI_MIN_AREA = 16384;
|
|||||||
static int constexpr DEFAULT_II_MIN_BYTES = 1024;
|
static int constexpr DEFAULT_II_MIN_BYTES = 1024;
|
||||||
|
|
||||||
QPDFJob::Members::Members() :
|
QPDFJob::Members::Members() :
|
||||||
|
log(QPDFLogger::defaultLogger()),
|
||||||
message_prefix("qpdf"),
|
message_prefix("qpdf"),
|
||||||
warnings(false),
|
warnings(false),
|
||||||
cout(&std::cout),
|
|
||||||
cerr(&std::cerr),
|
|
||||||
encryption_status(0),
|
encryption_status(0),
|
||||||
verbose(false),
|
verbose(false),
|
||||||
password(0),
|
password(0),
|
||||||
@ -442,19 +438,31 @@ QPDFJob::setMessagePrefix(std::string const& message_prefix)
|
|||||||
this->m->message_prefix = message_prefix;
|
this->m->message_prefix = message_prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<QPDFLogger>
|
||||||
|
QPDFJob::getLogger()
|
||||||
|
{
|
||||||
|
return this->m->log;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFJob::setLogger(std::shared_ptr<QPDFLogger> l)
|
||||||
|
{
|
||||||
|
this->m->log = l;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
|
QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
|
||||||
{
|
{
|
||||||
this->m->cout = out ? out : &std::cout;
|
setLogger(std::make_shared<QPDFLogger>());
|
||||||
this->m->cerr = err ? err : &std::cerr;
|
this->m->log->setOutputStreams(out, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFJob::doIfVerbose(
|
QPDFJob::doIfVerbose(
|
||||||
std::function<void(std::ostream&, std::string const& prefix)> fn)
|
std::function<void(Pipeline&, std::string const& prefix)> fn)
|
||||||
{
|
{
|
||||||
if (this->m->verbose && (this->m->cout != nullptr)) {
|
if (this->m->verbose) {
|
||||||
fn(*(this->m->cout), this->m->message_prefix);
|
fn(*this->m->log->getInfo(), this->m->message_prefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,14 +595,13 @@ QPDFJob::run()
|
|||||||
}
|
}
|
||||||
if (this->m->warnings && (!this->m->suppress_warnings)) {
|
if (this->m->warnings && (!this->m->suppress_warnings)) {
|
||||||
if (createsOutput()) {
|
if (createsOutput()) {
|
||||||
(*this->m->cerr)
|
*this->m->log->getWarn()
|
||||||
<< this->m->message_prefix
|
<< this->m->message_prefix
|
||||||
<< ": operation succeeded with warnings;"
|
<< ": operation succeeded with warnings;"
|
||||||
<< " resulting file may have some problems" << std::endl;
|
<< " resulting file may have some problems\n";
|
||||||
} else {
|
} else {
|
||||||
(*this->m->cerr)
|
*this->m->log->getWarn() << this->m->message_prefix
|
||||||
<< this->m->message_prefix
|
<< ": operation succeeded with warnings\n";
|
||||||
<< ": operation succeeded with warnings" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -722,7 +729,7 @@ QPDFJob::getEncryptionStatus()
|
|||||||
void
|
void
|
||||||
QPDFJob::setQPDFOptions(QPDF& pdf)
|
QPDFJob::setQPDFOptions(QPDF& pdf)
|
||||||
{
|
{
|
||||||
pdf.setOutputStreams(this->m->cout, this->m->cerr);
|
pdf.setLogger(this->m->log);
|
||||||
if (m->ignore_xref_streams) {
|
if (m->ignore_xref_streams) {
|
||||||
pdf.setIgnoreXRefStreams(true);
|
pdf.setIgnoreXRefStreams(true);
|
||||||
}
|
}
|
||||||
@ -778,50 +785,47 @@ 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;
|
auto& cout = *this->m->log->getInfo();
|
||||||
if (!pdf.isEncrypted(R, P, V, stream_method, string_method, file_method)) {
|
if (!pdf.isEncrypted(R, P, V, stream_method, string_method, file_method)) {
|
||||||
cout << "File is not encrypted" << std::endl;
|
cout << "File is not encrypted\n";
|
||||||
} else {
|
} else {
|
||||||
cout << "R = " << R << std::endl;
|
cout << "R = " << R << "\n";
|
||||||
cout << "P = " << P << std::endl;
|
cout << "P = " << P << "\n";
|
||||||
std::string user_password = pdf.getTrimmedUserPassword();
|
std::string user_password = pdf.getTrimmedUserPassword();
|
||||||
std::string encryption_key = pdf.getEncryptionKey();
|
std::string encryption_key = pdf.getEncryptionKey();
|
||||||
cout << "User password = " << user_password << std::endl;
|
cout << "User password = " << user_password << "\n";
|
||||||
if (m->show_encryption_key) {
|
if (m->show_encryption_key) {
|
||||||
cout << "Encryption key = " << QUtil::hex_encode(encryption_key)
|
cout << "Encryption key = " << QUtil::hex_encode(encryption_key)
|
||||||
<< std::endl;
|
<< "\n";
|
||||||
}
|
}
|
||||||
if (pdf.ownerPasswordMatched()) {
|
if (pdf.ownerPasswordMatched()) {
|
||||||
cout << "Supplied password is owner password" << std::endl;
|
cout << "Supplied password is owner password\n";
|
||||||
}
|
}
|
||||||
if (pdf.userPasswordMatched()) {
|
if (pdf.userPasswordMatched()) {
|
||||||
cout << "Supplied password is user password" << std::endl;
|
cout << "Supplied password is user password\n";
|
||||||
}
|
}
|
||||||
cout << "extract for accessibility: "
|
cout << "extract for accessibility: "
|
||||||
<< show_bool(pdf.allowAccessibility()) << std::endl
|
<< show_bool(pdf.allowAccessibility()) << "\n"
|
||||||
<< "extract for any purpose: " << show_bool(pdf.allowExtractAll())
|
<< "extract for any purpose: " << show_bool(pdf.allowExtractAll())
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< "print low resolution: " << show_bool(pdf.allowPrintLowRes())
|
<< "print low resolution: " << show_bool(pdf.allowPrintLowRes())
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< "print high resolution: " << show_bool(pdf.allowPrintHighRes())
|
<< "print high resolution: " << show_bool(pdf.allowPrintHighRes())
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< "modify document assembly: "
|
<< "modify document assembly: "
|
||||||
<< show_bool(pdf.allowModifyAssembly()) << std::endl
|
<< show_bool(pdf.allowModifyAssembly()) << "\n"
|
||||||
<< "modify forms: " << show_bool(pdf.allowModifyForm())
|
<< "modify forms: " << show_bool(pdf.allowModifyForm()) << "\n"
|
||||||
<< std::endl
|
|
||||||
<< "modify annotations: " << show_bool(pdf.allowModifyAnnotation())
|
<< "modify annotations: " << show_bool(pdf.allowModifyAnnotation())
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< "modify other: " << show_bool(pdf.allowModifyOther())
|
<< "modify other: " << show_bool(pdf.allowModifyOther()) << "\n"
|
||||||
<< std::endl
|
<< "modify anything: " << show_bool(pdf.allowModifyAll()) << "\n";
|
||||||
<< "modify anything: " << show_bool(pdf.allowModifyAll())
|
|
||||||
<< std::endl;
|
|
||||||
if (V >= 4) {
|
if (V >= 4) {
|
||||||
cout << "stream encryption method: "
|
cout << "stream encryption method: "
|
||||||
<< show_encryption_method(stream_method) << std::endl
|
<< show_encryption_method(stream_method) << "\n"
|
||||||
<< "string encryption method: "
|
<< "string encryption method: "
|
||||||
<< show_encryption_method(string_method) << std::endl
|
<< show_encryption_method(string_method) << "\n"
|
||||||
<< "file encryption method: "
|
<< "file encryption method: "
|
||||||
<< show_encryption_method(file_method) << std::endl;
|
<< show_encryption_method(file_method) << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -835,15 +839,15 @@ QPDFJob::doCheck(QPDF& pdf)
|
|||||||
// errors.
|
// errors.
|
||||||
bool okay = true;
|
bool okay = true;
|
||||||
bool warnings = false;
|
bool warnings = false;
|
||||||
auto& cout = *this->m->cout;
|
auto& cout = *this->m->log->getInfo();
|
||||||
cout << "checking " << m->infilename << std::endl;
|
cout << "checking " << m->infilename.get() << "\n";
|
||||||
try {
|
try {
|
||||||
int extension_level = pdf.getExtensionLevel();
|
int extension_level = pdf.getExtensionLevel();
|
||||||
cout << "PDF Version: " << pdf.getPDFVersion();
|
cout << "PDF Version: " << pdf.getPDFVersion();
|
||||||
if (extension_level > 0) {
|
if (extension_level > 0) {
|
||||||
cout << " extension level " << pdf.getExtensionLevel();
|
cout << " extension level " << pdf.getExtensionLevel();
|
||||||
}
|
}
|
||||||
cout << std::endl;
|
cout << "\n";
|
||||||
showEncryption(pdf);
|
showEncryption(pdf);
|
||||||
if (pdf.isLinearized()) {
|
if (pdf.isLinearized()) {
|
||||||
cout << "File is linearized\n";
|
cout << "File is linearized\n";
|
||||||
@ -875,12 +879,12 @@ QPDFJob::doCheck(QPDF& pdf)
|
|||||||
page.parseContents(&discard_contents);
|
page.parseContents(&discard_contents);
|
||||||
} catch (QPDFExc& e) {
|
} catch (QPDFExc& e) {
|
||||||
okay = false;
|
okay = false;
|
||||||
*(this->m->cerr) << "ERROR: page " << pageno << ": " << e.what()
|
*this->m->log->getError()
|
||||||
<< std::endl;
|
<< "ERROR: page " << pageno << ": " << e.what() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
(*this->m->cerr) << "ERROR: " << e.what() << std::endl;
|
*this->m->log->getError() << "ERROR: " << e.what() << "\n";
|
||||||
okay = false;
|
okay = false;
|
||||||
}
|
}
|
||||||
if (!okay) {
|
if (!okay) {
|
||||||
@ -890,9 +894,9 @@ QPDFJob::doCheck(QPDF& pdf)
|
|||||||
if ((!pdf.getWarnings().empty()) || warnings) {
|
if ((!pdf.getWarnings().empty()) || warnings) {
|
||||||
this->m->warnings = true;
|
this->m->warnings = true;
|
||||||
} else {
|
} else {
|
||||||
*(this->m->cout) << "No syntax or stream encoding errors"
|
*this->m->log->getInfo() << "No syntax or stream encoding errors"
|
||||||
<< " found; the file may still contain" << std::endl
|
<< " found; the file may still contain\n"
|
||||||
<< "errors that qpdf cannot detect" << std::endl;
|
<< "errors that qpdf cannot detect\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -922,11 +926,11 @@ QPDFJob::doShowObj(QPDF& pdf)
|
|||||||
filter ? qpdf_dl_all : qpdf_dl_none);
|
filter ? qpdf_dl_all : qpdf_dl_none);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*(this->m->cout) << "Object is stream. Dictionary:" << std::endl
|
*this->m->log->getInfo() << "Object is stream. Dictionary:\n"
|
||||||
<< obj.getDict().unparseResolved() << std::endl;
|
<< obj.getDict().unparseResolved() << "\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*(this->m->cout) << obj.unparseResolved() << std::endl;
|
*this->m->log->getInfo() << obj.unparseResolved() << "\n";
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
@ -938,17 +942,17 @@ void
|
|||||||
QPDFJob::doShowPages(QPDF& pdf)
|
QPDFJob::doShowPages(QPDF& pdf)
|
||||||
{
|
{
|
||||||
int pageno = 0;
|
int pageno = 0;
|
||||||
auto& cout = *this->m->cout;
|
auto& cout = *this->m->log->getInfo();
|
||||||
for (auto& ph: QPDFPageDocumentHelper(pdf).getAllPages()) {
|
for (auto& ph: QPDFPageDocumentHelper(pdf).getAllPages()) {
|
||||||
QPDFObjectHandle page = ph.getObjectHandle();
|
QPDFObjectHandle page = ph.getObjectHandle();
|
||||||
++pageno;
|
++pageno;
|
||||||
|
|
||||||
cout << "page " << pageno << ": " << page.getObjectID() << " "
|
cout << "page " << pageno << ": " << page.getObjectID() << " "
|
||||||
<< page.getGeneration() << " R" << std::endl;
|
<< page.getGeneration() << " R\n";
|
||||||
if (m->show_page_images) {
|
if (m->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()) {
|
||||||
cout << " images:" << std::endl;
|
cout << " images:\n";
|
||||||
for (auto const& iter2: images) {
|
for (auto const& iter2: images) {
|
||||||
std::string const& name = iter2.first;
|
std::string const& name = iter2.first;
|
||||||
QPDFObjectHandle image = iter2.second;
|
QPDFObjectHandle image = iter2.second;
|
||||||
@ -956,14 +960,14 @@ QPDFJob::doShowPages(QPDF& pdf)
|
|||||||
int width = dict.getKey("/Width").getIntValueAsInt();
|
int width = dict.getKey("/Width").getIntValueAsInt();
|
||||||
int height = dict.getKey("/Height").getIntValueAsInt();
|
int height = dict.getKey("/Height").getIntValueAsInt();
|
||||||
cout << " " << name << ": " << image.unparse() << ", "
|
cout << " " << name << ": " << image.unparse() << ", "
|
||||||
<< width << " x " << height << std::endl;
|
<< width << " x " << height << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << " content:" << std::endl;
|
cout << " content:\n";
|
||||||
for (auto& iter2: ph.getPageContents()) {
|
for (auto& iter2: ph.getPageContents()) {
|
||||||
cout << " " << iter2.unparse() << std::endl;
|
cout << " " << iter2.unparse() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -976,39 +980,36 @@ QPDFJob::doListAttachments(QPDF& pdf)
|
|||||||
for (auto const& i: efdh.getEmbeddedFiles()) {
|
for (auto const& i: efdh.getEmbeddedFiles()) {
|
||||||
std::string const& key = i.first;
|
std::string const& key = i.first;
|
||||||
auto efoh = i.second;
|
auto efoh = i.second;
|
||||||
*(this->m->cout)
|
*this->m->log->getInfo()
|
||||||
<< key << " -> " << efoh->getEmbeddedFileStream().getObjGen()
|
<< key << " -> "
|
||||||
<< std::endl;
|
<< efoh->getEmbeddedFileStream().getObjGen().unparse() << "\n";
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
auto desc = efoh->getDescription();
|
auto desc = efoh->getDescription();
|
||||||
if (!desc.empty()) {
|
if (!desc.empty()) {
|
||||||
cout << " description: " << desc << std::endl;
|
v << " description: " << desc << "\n";
|
||||||
}
|
}
|
||||||
cout << " preferred name: " << efoh->getFilename()
|
v << " preferred name: " << efoh->getFilename() << "\n";
|
||||||
<< std::endl;
|
v << " all names:\n";
|
||||||
cout << " all names:" << std::endl;
|
|
||||||
for (auto const& i2: efoh->getFilenames()) {
|
for (auto const& i2: efoh->getFilenames()) {
|
||||||
cout << " " << i2.first << " -> " << i2.second
|
v << " " << i2.first << " -> " << i2.second << "\n";
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
cout << " all data streams:" << std::endl;
|
v << " all data streams:\n";
|
||||||
for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
|
for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
|
||||||
auto efs = QPDFEFStreamObjectHelper(i2.second);
|
auto efs = QPDFEFStreamObjectHelper(i2.second);
|
||||||
cout << " " << i2.first << " -> "
|
v << " " << i2.first << " -> "
|
||||||
<< efs.getObjectHandle().getObjGen() << std::endl;
|
<< efs.getObjectHandle().getObjGen().unparse() << "\n";
|
||||||
cout << " creation date: " << efs.getCreationDate()
|
v << " creation date: " << efs.getCreationDate()
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< " modification date: " << efs.getModDate()
|
<< " modification date: " << efs.getModDate() << "\n"
|
||||||
<< std::endl
|
<< " mime type: " << efs.getSubtype() << "\n"
|
||||||
<< " mime type: " << efs.getSubtype() << std::endl
|
<< " checksum: "
|
||||||
<< " checksum: "
|
<< QUtil::hex_encode(efs.getChecksum()) << "\n";
|
||||||
<< QUtil::hex_encode(efs.getChecksum()) << std::endl;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*(this->m->cout) << m->infilename << " has no embedded files"
|
*this->m->log->getInfo()
|
||||||
<< std::endl;
|
<< m->infilename.get() << " has no embedded files\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1816,11 +1817,10 @@ QPDFJob::doJSON(QPDF& pdf, Pipeline* p)
|
|||||||
std::list<std::string> errors;
|
std::list<std::string> errors;
|
||||||
JSON captured = JSON::parse(captured_json);
|
JSON captured = JSON::parse(captured_json);
|
||||||
if (!captured.checkSchema(schema, errors)) {
|
if (!captured.checkSchema(schema, errors)) {
|
||||||
*(this->m->cerr) << "QPDFJob didn't create JSON that complies with"
|
this->m->log->error("QPDFJob didn't create JSON that complies with "
|
||||||
" its own rules."
|
"its own rules.\n");
|
||||||
<< std::endl;
|
|
||||||
for (auto const& error: errors) {
|
for (auto const& error: errors) {
|
||||||
*(this->m->cerr) << error << std::endl;
|
*this->m->log->getError() << error << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1829,30 +1829,26 @@ QPDFJob::doJSON(QPDF& pdf, Pipeline* p)
|
|||||||
void
|
void
|
||||||
QPDFJob::doInspection(QPDF& pdf)
|
QPDFJob::doInspection(QPDF& pdf)
|
||||||
{
|
{
|
||||||
|
auto& cout = *this->m->log->getInfo();
|
||||||
if (m->check) {
|
if (m->check) {
|
||||||
doCheck(pdf);
|
doCheck(pdf);
|
||||||
}
|
}
|
||||||
if (m->json_version) {
|
if (m->json_version) {
|
||||||
Pl_OStream os("stdout", *(this->m->cout));
|
doJSON(pdf, &cout);
|
||||||
doJSON(pdf, &os);
|
|
||||||
os.finish();
|
|
||||||
}
|
}
|
||||||
if (m->show_npages) {
|
if (m->show_npages) {
|
||||||
QTC::TC("qpdf", "QPDFJob npages");
|
QTC::TC("qpdf", "QPDFJob npages");
|
||||||
*(this->m->cout)
|
cout << pdf.getRoot().getKey("/Pages").getKey("/Count").getIntValue()
|
||||||
<< pdf.getRoot().getKey("/Pages").getKey("/Count").getIntValue()
|
<< "\n";
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
if (m->show_encryption) {
|
if (m->show_encryption) {
|
||||||
showEncryption(pdf);
|
showEncryption(pdf);
|
||||||
}
|
}
|
||||||
if (m->check_linearization) {
|
if (m->check_linearization) {
|
||||||
if (!pdf.isLinearized()) {
|
if (!pdf.isLinearized()) {
|
||||||
*(this->m->cout)
|
cout << m->infilename.get() << " is not linearized\n";
|
||||||
<< m->infilename << " is not linearized" << std::endl;
|
|
||||||
} else if (pdf.checkLinearization()) {
|
} else if (pdf.checkLinearization()) {
|
||||||
*(this->m->cout)
|
cout << m->infilename.get() << ": no linearization errors\n";
|
||||||
<< m->infilename << ": no linearization errors" << std::endl;
|
|
||||||
} else {
|
} else {
|
||||||
this->m->warnings = true;
|
this->m->warnings = true;
|
||||||
}
|
}
|
||||||
@ -1861,8 +1857,7 @@ QPDFJob::doInspection(QPDF& pdf)
|
|||||||
if (pdf.isLinearized()) {
|
if (pdf.isLinearized()) {
|
||||||
pdf.showLinearizationData();
|
pdf.showLinearizationData();
|
||||||
} else {
|
} else {
|
||||||
*(this->m->cout)
|
cout << m->infilename.get() << " is not linearized\n";
|
||||||
<< m->infilename << " is not linearized" << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m->show_xref) {
|
if (m->show_xref) {
|
||||||
@ -1979,11 +1974,10 @@ QPDFJob::doProcess(
|
|||||||
}
|
}
|
||||||
if (!warned) {
|
if (!warned) {
|
||||||
warned = true;
|
warned = true;
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": supplied password didn't work;"
|
v << 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\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2097,8 +2091,8 @@ QPDFJob::doUnderOverlayForPage(
|
|||||||
"/Resources", QPDFObjectHandle::newDictionary());
|
"/Resources", QPDFObjectHandle::newDictionary());
|
||||||
}
|
}
|
||||||
for (int from_pageno: pagenos[pageno]) {
|
for (int from_pageno: pagenos[pageno]) {
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << " " << uo.which << " " << from_pageno << std::endl;
|
v << " " << uo.which << " " << from_pageno << "\n";
|
||||||
});
|
});
|
||||||
auto from_page = pages.at(QIntC::to_size(from_pageno - 1));
|
auto from_page = pages.at(QIntC::to_size(from_pageno - 1));
|
||||||
if (0 == fo.count(from_pageno)) {
|
if (0 == fo.count(from_pageno)) {
|
||||||
@ -2187,12 +2181,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();
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": processing underlay/overlay" << std::endl;
|
v << prefix << ": processing underlay/overlay\n";
|
||||||
});
|
});
|
||||||
for (size_t i = 0; i < main_npages; ++i) {
|
for (size_t i = 0; i < main_npages; ++i) {
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << " page " << 1 + i << std::endl;
|
v << " page " << 1 + i << "\n";
|
||||||
});
|
});
|
||||||
doUnderOverlayForPage(
|
doUnderOverlayForPage(
|
||||||
pdf,
|
pdf,
|
||||||
@ -2248,9 +2242,9 @@ QPDFJob::addAttachments(QPDF& pdf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
efdh.replaceEmbeddedFile(to_add.key, fs);
|
efdh.replaceEmbeddedFile(to_add.key, fs);
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": attached " << to_add.path << " as "
|
v << prefix << ": attached " << to_add.path << " as "
|
||||||
<< to_add.filename << " with key " << to_add.key << std::endl;
|
<< to_add.filename << " with key " << to_add.key << "\n";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2276,9 +2270,9 @@ QPDFJob::copyAttachments(QPDF& pdf)
|
|||||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||||
std::vector<std::string> duplicates;
|
std::vector<std::string> duplicates;
|
||||||
for (auto const& to_copy: m->attachments_to_copy) {
|
for (auto const& to_copy: m->attachments_to_copy) {
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": copying attachments from " << to_copy.path
|
v << prefix << ": copying attachments from " << to_copy.path
|
||||||
<< std::endl;
|
<< "\n";
|
||||||
});
|
});
|
||||||
auto other = processFile(
|
auto other = processFile(
|
||||||
to_copy.path.c_str(), to_copy.password.c_str(), false, false);
|
to_copy.path.c_str(), to_copy.password.c_str(), false, false);
|
||||||
@ -2294,9 +2288,8 @@ QPDFJob::copyAttachments(QPDF& pdf)
|
|||||||
pdf.copyForeignObject(iter.second->getObjectHandle());
|
pdf.copyForeignObject(iter.second->getObjectHandle());
|
||||||
efdh.replaceEmbeddedFile(
|
efdh.replaceEmbeddedFile(
|
||||||
new_key, QPDFFileSpecObjectHelper(new_fs_oh));
|
new_key, QPDFFileSpecObjectHelper(new_fs_oh));
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << " " << iter.first << " -> " << new_key
|
v << " " << iter.first << " -> " << new_key << "\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2398,9 +2391,8 @@ QPDFJob::handleTransformations(QPDF& pdf)
|
|||||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||||
for (auto const& key: m->attachments_to_remove) {
|
for (auto const& key: m->attachments_to_remove) {
|
||||||
if (efdh.removeEmbeddedFile(key)) {
|
if (efdh.removeEmbeddedFile(key)) {
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": removed attachment " << key
|
v << prefix << ": removed attachment " << key << "\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("attachment " + key + " not found");
|
throw std::runtime_error("attachment " + key + " not found");
|
||||||
@ -2437,9 +2429,9 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
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
|
||||||
|
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": " << pdf.getFilename()
|
v << prefix << ": " << pdf.getFilename()
|
||||||
<< ": checking for shared resources" << std::endl;
|
<< ": checking for shared resources\n";
|
||||||
});
|
});
|
||||||
|
|
||||||
std::list<QPDFObjectHandle> queue;
|
std::list<QPDFObjectHandle> queue;
|
||||||
@ -2458,9 +2450,9 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
// This is a non-leaf node.
|
// This is a non-leaf node.
|
||||||
if (dict.hasKey("/Resources")) {
|
if (dict.hasKey("/Resources")) {
|
||||||
QTC::TC("qpdf", "QPDFJob found resources in non-leaf");
|
QTC::TC("qpdf", "QPDFJob found resources in non-leaf");
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << " found resources in non-leaf page node "
|
v << " found resources in non-leaf page node "
|
||||||
<< og.getObj() << " " << og.getGen() << std::endl;
|
<< og.getObj() << " " << og.getGen() << "\n";
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2475,13 +2467,12 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
QPDFObjGen resources_og = resources.getObjGen();
|
QPDFObjGen resources_og = resources.getObjGen();
|
||||||
if (resources_seen.count(resources_og)) {
|
if (resources_seen.count(resources_og)) {
|
||||||
QTC::TC("qpdf", "QPDFJob found shared resources in leaf");
|
QTC::TC("qpdf", "QPDFJob found shared resources in leaf");
|
||||||
doIfVerbose(
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
[&](std::ostream& cout, std::string const& prefix) {
|
v << " found shared resources in leaf node "
|
||||||
cout << " found shared resources in leaf node "
|
<< og.getObj() << " " << og.getGen() << ": "
|
||||||
<< og.getObj() << " " << og.getGen() << ": "
|
<< resources_og.getObj() << " "
|
||||||
<< resources_og.getObj() << " "
|
<< resources_og.getGen() << "\n";
|
||||||
<< resources_og.getGen() << std::endl;
|
});
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
resources_seen.insert(resources_og);
|
resources_seen.insert(resources_og);
|
||||||
@ -2493,13 +2484,12 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
QPDFObjGen xobject_og = xobject.getObjGen();
|
QPDFObjGen xobject_og = xobject.getObjGen();
|
||||||
if (resources_seen.count(xobject_og)) {
|
if (resources_seen.count(xobject_og)) {
|
||||||
QTC::TC("qpdf", "QPDFJob found shared xobject in leaf");
|
QTC::TC("qpdf", "QPDFJob found shared xobject in leaf");
|
||||||
doIfVerbose(
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
[&](std::ostream& cout, std::string const& prefix) {
|
v << " found shared xobject in leaf node "
|
||||||
cout << " found shared xobject in leaf node "
|
<< og.getObj() << " " << og.getGen() << ": "
|
||||||
<< og.getObj() << " " << og.getGen() << ": "
|
<< xobject_og.getObj() << " " << xobject_og.getGen()
|
||||||
<< xobject_og.getObj() << " "
|
<< "\n";
|
||||||
<< xobject_og.getGen() << std::endl;
|
});
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
resources_seen.insert(xobject_og);
|
resources_seen.insert(xobject_og);
|
||||||
@ -2515,8 +2505,8 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": no shared resources found" << std::endl;
|
v << prefix << ": no shared resources found\n";
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2567,9 +2557,9 @@ QPDFJob::handlePageSpecs(
|
|||||||
"qpdf",
|
"qpdf",
|
||||||
"QPDFJob automatically set keep files open",
|
"QPDFJob automatically set keep files open",
|
||||||
m->keep_files_open ? 0 : 1);
|
m->keep_files_open ? 0 : 1);
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": selecting --keep-open-files="
|
v << prefix << ": selecting --keep-open-files="
|
||||||
<< (m->keep_files_open ? "y" : "n") << std::endl;
|
<< (m->keep_files_open ? "y" : "n") << "\n";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2597,9 +2587,8 @@ QPDFJob::handlePageSpecs(
|
|||||||
QTC::TC("qpdf", "QPDFJob pages encryption password");
|
QTC::TC("qpdf", "QPDFJob pages encryption password");
|
||||||
password = m->encryption_file_password.get();
|
password = m->encryption_file_password.get();
|
||||||
}
|
}
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": processing " << page_spec.filename
|
v << prefix << ": processing " << page_spec.filename << "\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
std::shared_ptr<InputSource> is;
|
std::shared_ptr<InputSource> is;
|
||||||
ClosedFileInputSource* cis = 0;
|
ClosedFileInputSource* cis = 0;
|
||||||
@ -2660,9 +2649,8 @@ QPDFJob::handlePageSpecs(
|
|||||||
// 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.
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": removing unreferenced pages from primary input"
|
v << prefix << ": removing unreferenced pages from primary input\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
QPDFPageDocumentHelper dh(pdf);
|
QPDFPageDocumentHelper dh(pdf);
|
||||||
std::vector<QPDFPageObjectHelper> orig_pages = dh.getAllPages();
|
std::vector<QPDFPageObjectHelper> orig_pages = dh.getAllPages();
|
||||||
@ -2720,9 +2708,8 @@ QPDFJob::handlePageSpecs(
|
|||||||
if (pldh.hasPageLabels()) {
|
if (pldh.hasPageLabels()) {
|
||||||
any_page_labels = true;
|
any_page_labels = true;
|
||||||
}
|
}
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": adding pages from " << page_data.filename
|
v << prefix << ": adding pages from " << page_data.filename << "\n";
|
||||||
<< std::endl;
|
|
||||||
});
|
});
|
||||||
for (auto pageno_iter: page_data.selected_pages) {
|
for (auto pageno_iter: page_data.selected_pages) {
|
||||||
// Pages are specified from 1 but numbered from 0 in the
|
// Pages are specified from 1 but numbered from 0 in the
|
||||||
@ -2910,18 +2897,17 @@ QPDFJob::maybeFixWritePassword(int R, std::string& password)
|
|||||||
std::string encoded;
|
std::string encoded;
|
||||||
if (QUtil::utf8_to_pdf_doc(password, encoded)) {
|
if (QUtil::utf8_to_pdf_doc(password, encoded)) {
|
||||||
QTC::TC("qpdf", "QPDFJob auto-encode password");
|
QTC::TC("qpdf", "QPDFJob auto-encode password");
|
||||||
doIfVerbose(
|
doIfVerbose([&](Pipeline& v,
|
||||||
[&](std::ostream& cout, std::string const& prefix) {
|
std::string const& prefix) {
|
||||||
cout << prefix
|
v << 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"
|
<< " encryption\n";
|
||||||
<< " encryption" << std::endl;
|
});
|
||||||
});
|
|
||||||
password = encoded;
|
password = encoded;
|
||||||
} else {
|
} else {
|
||||||
QTC::TC("qpdf", "QPDFJob bytes fallback warning");
|
QTC::TC("qpdf", "QPDFJob bytes fallback warning");
|
||||||
*(this->m->cerr)
|
*this->m->log->getError()
|
||||||
<< this->m->message_prefix << ": 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"
|
||||||
@ -2929,8 +2915,7 @@ QPDFJob::maybeFixWritePassword(int R, std::string& password)
|
|||||||
<< " most readers will not be able to open this"
|
<< " most readers will not be able to open this"
|
||||||
<< " file with the supplied password."
|
<< " file with the supplied password."
|
||||||
<< " (Use --password-mode=bytes to suppress this"
|
<< " (Use --password-mode=bytes to suppress this"
|
||||||
<< " warning and use the password anyway.)"
|
<< " warning and use the password anyway.)\n";
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
} else if ((R >= 5) && (!is_valid_utf8)) {
|
} else if ((R >= 5) && (!is_valid_utf8)) {
|
||||||
QTC::TC("qpdf", "QPDFJob invalid utf-8 in auto");
|
QTC::TC("qpdf", "QPDFJob invalid utf-8 in auto");
|
||||||
@ -2968,26 +2953,24 @@ QPDFJob::setEncryptionOptions(QPDF& pdf, QPDFWriter& w)
|
|||||||
throw std::logic_error("bad encryption keylen");
|
throw std::logic_error("bad encryption keylen");
|
||||||
}
|
}
|
||||||
if ((R > 3) && (m->r3_accessibility == false)) {
|
if ((R > 3) && (m->r3_accessibility == false)) {
|
||||||
*(this->m->cerr) << this->m->message_prefix
|
*this->m->log->getError() << this->m->message_prefix
|
||||||
<< ": -accessibility=n is ignored for modern"
|
<< ": -accessibility=n is ignored for modern"
|
||||||
<< " encryption formats" << std::endl;
|
<< " encryption formats\n";
|
||||||
}
|
}
|
||||||
maybeFixWritePassword(R, m->user_password);
|
maybeFixWritePassword(R, m->user_password);
|
||||||
maybeFixWritePassword(R, m->owner_password);
|
maybeFixWritePassword(R, m->owner_password);
|
||||||
if ((R < 4) || ((R == 4) && (!m->use_aes))) {
|
if ((R < 4) || ((R == 4) && (!m->use_aes))) {
|
||||||
if (!m->allow_weak_crypto) {
|
if (!m->allow_weak_crypto) {
|
||||||
QTC::TC("qpdf", "QPDFJob weak crypto error");
|
QTC::TC("qpdf", "QPDFJob weak crypto error");
|
||||||
*(this->m->cerr)
|
*this->m->log->getError()
|
||||||
<< this->m->message_prefix
|
<< this->m->message_prefix
|
||||||
<< ": refusing to write a file with RC4, a weak cryptographic "
|
<< ": refusing to write a file with RC4, a weak cryptographic "
|
||||||
"algorithm"
|
"algorithm\n"
|
||||||
<< std::endl
|
<< "Please use 256-bit keys for better security.\n"
|
||||||
<< "Please use 256-bit keys for better security." << std::endl
|
<< "Pass --allow-weak-crypto to enable writing insecure "
|
||||||
<< "Pass --allow-weak-crypto to enable writing insecure files."
|
"files.\n"
|
||||||
<< std::endl
|
|
||||||
<< "See also "
|
<< "See also "
|
||||||
"https://qpdf.readthedocs.io/en/stable/weak-crypto.html"
|
"https://qpdf.readthedocs.io/en/stable/weak-crypto.html\n";
|
||||||
<< std::endl;
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"refusing to write a file with weak crypto");
|
"refusing to write a file with weak crypto");
|
||||||
}
|
}
|
||||||
@ -3160,7 +3143,7 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w)
|
|||||||
std::shared_ptr<QPDFWriter::ProgressReporter>(
|
std::shared_ptr<QPDFWriter::ProgressReporter>(
|
||||||
// line-break
|
// line-break
|
||||||
new ProgressReporter(
|
new ProgressReporter(
|
||||||
*(this->m->cout),
|
*this->m->log->getInfo(),
|
||||||
this->m->message_prefix,
|
this->m->message_prefix,
|
||||||
m->outfilename.get())));
|
m->outfilename.get())));
|
||||||
}
|
}
|
||||||
@ -3260,8 +3243,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();
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": wrote file " << outfile << std::endl;
|
v << prefix << ": wrote file " << outfile << "\n";
|
||||||
});
|
});
|
||||||
if (outpdf.anyWarnings()) {
|
if (outpdf.anyWarnings()) {
|
||||||
warnings = true;
|
warnings = true;
|
||||||
@ -3295,8 +3278,8 @@ QPDFJob::writeOutfile(QPDF& pdf)
|
|||||||
w.write();
|
w.write();
|
||||||
}
|
}
|
||||||
if (m->outfilename) {
|
if (m->outfilename) {
|
||||||
doIfVerbose([&](std::ostream& cout, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
cout << prefix << ": wrote file " << m->outfilename << std::endl;
|
v << prefix << ": wrote file " << m->outfilename.get() << "\n";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (m->replace_input) {
|
if (m->replace_input) {
|
||||||
@ -3313,18 +3296,19 @@ QPDFJob::writeOutfile(QPDF& pdf)
|
|||||||
QUtil::rename_file(m->infilename.get(), backup.c_str());
|
QUtil::rename_file(m->infilename.get(), backup.c_str());
|
||||||
QUtil::rename_file(temp_out.get(), m->infilename.get());
|
QUtil::rename_file(temp_out.get(), m->infilename.get());
|
||||||
if (warnings) {
|
if (warnings) {
|
||||||
*(this->m->cerr) << this->m->message_prefix
|
*this->m->log->getError()
|
||||||
<< ": there are warnings; original file kept in "
|
<< this->m->message_prefix
|
||||||
<< backup << std::endl;
|
<< ": there are warnings; original file kept in " << backup
|
||||||
|
<< "\n";
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
QUtil::remove_file(backup.c_str());
|
QUtil::remove_file(backup.c_str());
|
||||||
} catch (QPDFSystemError& e) {
|
} catch (QPDFSystemError& e) {
|
||||||
*(this->m->cerr)
|
*this->m->log->getError()
|
||||||
<< this->m->message_prefix
|
<< this->m->message_prefix
|
||||||
<< ": unable to delete original file (" << e.what() << ");"
|
<< ": unable to delete original file (" << e.what() << ");"
|
||||||
<< " original file left in " << backup
|
<< " original file left in " << backup
|
||||||
<< ", but the input was successfully replaced" << std::endl;
|
<< ", but the input was successfully replaced\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3353,7 +3337,7 @@ QPDFJob::writeJSON(QPDF& pdf)
|
|||||||
"name is unknown");
|
"name is unknown");
|
||||||
} else {
|
} else {
|
||||||
QTC::TC("qpdf", "QPDFJob write json to stdout");
|
QTC::TC("qpdf", "QPDFJob write json to stdout");
|
||||||
fp = std::make_shared<Pl_OStream>("json output", *this->m->cout);
|
fp = this->m->log->getInfo();
|
||||||
}
|
}
|
||||||
std::set<std::string> json_objects;
|
std::set<std::string> json_objects;
|
||||||
if (this->m->json_objects.count("trailer")) {
|
if (this->m->json_objects.count("trailer")) {
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <qpdf/Pl_Count.hh>
|
#include <qpdf/Pl_Count.hh>
|
||||||
#include <qpdf/Pl_Flate.hh>
|
#include <qpdf/Pl_Flate.hh>
|
||||||
#include <qpdf/QPDFExc.hh>
|
#include <qpdf/QPDFExc.hh>
|
||||||
|
#include <qpdf/QPDFLogger.hh>
|
||||||
#include <qpdf/QTC.hh>
|
#include <qpdf/QTC.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
@ -72,9 +73,9 @@ QPDF::checkLinearization()
|
|||||||
readLinearizationData();
|
readLinearizationData();
|
||||||
result = checkLinearizationInternal();
|
result = checkLinearizationInternal();
|
||||||
} catch (std::runtime_error& e) {
|
} catch (std::runtime_error& e) {
|
||||||
*this->m->err_stream
|
*this->m->log->getError()
|
||||||
<< "WARNING: error encountered while checking linearization data: "
|
<< "WARNING: error encountered while checking linearization data: "
|
||||||
<< e.what() << std::endl;
|
<< e.what() << "\n";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -360,9 +361,9 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
|
|||||||
}
|
}
|
||||||
qpdf_offset_t computed_end = offset + toO(length);
|
qpdf_offset_t computed_end = offset + toO(length);
|
||||||
if ((computed_end < min_end_offset) || (computed_end > max_end_offset)) {
|
if ((computed_end < min_end_offset) || (computed_end > max_end_offset)) {
|
||||||
*this->m->err_stream << "expected = " << computed_end
|
*this->m->log->getError()
|
||||||
<< "; actual = " << min_end_offset << ".."
|
<< "expected = " << computed_end << "; actual = " << min_end_offset
|
||||||
<< max_end_offset << std::endl;
|
<< ".." << max_end_offset << "\n";
|
||||||
throw QPDFExc(
|
throw QPDFExc(
|
||||||
qpdf_e_damaged_pdf,
|
qpdf_e_damaged_pdf,
|
||||||
this->m->file->getName(),
|
this->m->file->getName(),
|
||||||
@ -643,14 +644,14 @@ QPDF::checkLinearizationInternal()
|
|||||||
if (!errors.empty()) {
|
if (!errors.empty()) {
|
||||||
result = false;
|
result = false;
|
||||||
for (auto const& error: errors) {
|
for (auto const& error: errors) {
|
||||||
*this->m->err_stream << "WARNING: " << error << std::endl;
|
*this->m->log->getError() << "WARNING: " << error << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!warnings.empty()) {
|
if (!warnings.empty()) {
|
||||||
result = false;
|
result = false;
|
||||||
for (auto const& warning: warnings) {
|
for (auto const& warning: warnings) {
|
||||||
*this->m->err_stream << "WARNING: " << warning << std::endl;
|
*this->m->log->getError() << "WARNING: " << warning << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1013,39 +1014,34 @@ QPDF::showLinearizationData()
|
|||||||
checkLinearizationInternal();
|
checkLinearizationInternal();
|
||||||
dumpLinearizationDataInternal();
|
dumpLinearizationDataInternal();
|
||||||
} catch (QPDFExc& e) {
|
} catch (QPDFExc& e) {
|
||||||
*this->m->err_stream << e.what() << std::endl;
|
*this->m->log->getError() << e.what() << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::dumpLinearizationDataInternal()
|
QPDF::dumpLinearizationDataInternal()
|
||||||
{
|
{
|
||||||
*this->m->out_stream << this->m->file->getName()
|
*this->m->log->getInfo()
|
||||||
<< ": linearization data:" << std::endl
|
<< this->m->file->getName() << ": linearization data:\n\n";
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
*this->m->out_stream
|
*this->m->log->getInfo()
|
||||||
<< "file_size: " << this->m->linp.file_size << std::endl
|
<< "file_size: " << this->m->linp.file_size << "\n"
|
||||||
<< "first_page_object: " << this->m->linp.first_page_object << std::endl
|
<< "first_page_object: " << this->m->linp.first_page_object << "\n"
|
||||||
<< "first_page_end: " << this->m->linp.first_page_end << std::endl
|
<< "first_page_end: " << this->m->linp.first_page_end << "\n"
|
||||||
<< "npages: " << this->m->linp.npages << std::endl
|
<< "npages: " << this->m->linp.npages << "\n"
|
||||||
<< "xref_zero_offset: " << this->m->linp.xref_zero_offset << std::endl
|
<< "xref_zero_offset: " << this->m->linp.xref_zero_offset << "\n"
|
||||||
<< "first_page: " << this->m->linp.first_page << std::endl
|
<< "first_page: " << this->m->linp.first_page << "\n"
|
||||||
<< "H_offset: " << this->m->linp.H_offset << std::endl
|
<< "H_offset: " << this->m->linp.H_offset << "\n"
|
||||||
<< "H_length: " << this->m->linp.H_length << std::endl
|
<< "H_length: " << this->m->linp.H_length << "\n"
|
||||||
<< std::endl;
|
<< "\n";
|
||||||
|
|
||||||
*this->m->out_stream << "Page Offsets Hint Table" << std::endl << std::endl;
|
*this->m->log->getInfo() << "Page Offsets Hint Table\n\n";
|
||||||
dumpHPageOffset();
|
dumpHPageOffset();
|
||||||
*this->m->out_stream << std::endl
|
*this->m->log->getInfo() << "\nShared Objects Hint Table\n\n";
|
||||||
<< "Shared Objects Hint Table" << std::endl
|
|
||||||
<< std::endl;
|
|
||||||
dumpHSharedObject();
|
dumpHSharedObject();
|
||||||
|
|
||||||
if (this->m->outline_hints.nobjects > 0) {
|
if (this->m->outline_hints.nobjects > 0) {
|
||||||
*this->m->out_stream << std::endl
|
*this->m->log->getInfo() << "\nOutlines Hint Table\n\n";
|
||||||
<< "Outlines Hint Table" << std::endl
|
|
||||||
<< std::endl;
|
|
||||||
dumpHGeneric(this->m->outline_hints);
|
dumpHGeneric(this->m->outline_hints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1066,42 +1062,41 @@ void
|
|||||||
QPDF::dumpHPageOffset()
|
QPDF::dumpHPageOffset()
|
||||||
{
|
{
|
||||||
HPageOffset& t = this->m->page_offset_hints;
|
HPageOffset& t = this->m->page_offset_hints;
|
||||||
*this->m->out_stream
|
*this->m->log->getInfo()
|
||||||
<< "min_nobjects: " << t.min_nobjects << std::endl
|
<< "min_nobjects: " << t.min_nobjects << "\n"
|
||||||
<< "first_page_offset: " << adjusted_offset(t.first_page_offset)
|
<< "first_page_offset: " << adjusted_offset(t.first_page_offset) << "\n"
|
||||||
<< std::endl
|
<< "nbits_delta_nobjects: " << t.nbits_delta_nobjects << "\n"
|
||||||
<< "nbits_delta_nobjects: " << t.nbits_delta_nobjects << std::endl
|
<< "min_page_length: " << t.min_page_length << "\n"
|
||||||
<< "min_page_length: " << t.min_page_length << std::endl
|
<< "nbits_delta_page_length: " << t.nbits_delta_page_length << "\n"
|
||||||
<< "nbits_delta_page_length: " << t.nbits_delta_page_length << std::endl
|
<< "min_content_offset: " << t.min_content_offset << "\n"
|
||||||
<< "min_content_offset: " << t.min_content_offset << std::endl
|
|
||||||
<< "nbits_delta_content_offset: " << t.nbits_delta_content_offset
|
<< "nbits_delta_content_offset: " << t.nbits_delta_content_offset
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< "min_content_length: " << t.min_content_length << std::endl
|
<< "min_content_length: " << t.min_content_length << "\n"
|
||||||
<< "nbits_delta_content_length: " << t.nbits_delta_content_length
|
<< "nbits_delta_content_length: " << t.nbits_delta_content_length
|
||||||
<< std::endl
|
<< "\n"
|
||||||
<< "nbits_nshared_objects: " << t.nbits_nshared_objects << std::endl
|
<< "nbits_nshared_objects: " << t.nbits_nshared_objects << "\n"
|
||||||
<< "nbits_shared_identifier: " << t.nbits_shared_identifier << std::endl
|
<< "nbits_shared_identifier: " << t.nbits_shared_identifier << "\n"
|
||||||
<< "nbits_shared_numerator: " << t.nbits_shared_numerator << std::endl
|
<< "nbits_shared_numerator: " << t.nbits_shared_numerator << "\n"
|
||||||
<< "shared_denominator: " << t.shared_denominator << std::endl;
|
<< "shared_denominator: " << t.shared_denominator << "\n";
|
||||||
|
|
||||||
for (size_t i1 = 0; i1 < toS(this->m->linp.npages); ++i1) {
|
for (size_t i1 = 0; i1 < toS(this->m->linp.npages); ++i1) {
|
||||||
HPageOffsetEntry& pe = t.entries.at(i1);
|
HPageOffsetEntry& pe = t.entries.at(i1);
|
||||||
*this->m->out_stream
|
*this->m->log->getInfo()
|
||||||
<< "Page " << i1 << ":" << std::endl
|
<< "Page " << i1 << ":\n"
|
||||||
<< " nobjects: " << pe.delta_nobjects + t.min_nobjects << std::endl
|
<< " nobjects: " << pe.delta_nobjects + t.min_nobjects << "\n"
|
||||||
<< " length: " << pe.delta_page_length + t.min_page_length
|
<< " length: " << pe.delta_page_length + t.min_page_length
|
||||||
<< std::endl
|
<< "\n"
|
||||||
// content offset is relative to page, not file
|
// content offset is relative to page, not file
|
||||||
<< " content_offset: "
|
<< " content_offset: "
|
||||||
<< pe.delta_content_offset + t.min_content_offset << std::endl
|
<< pe.delta_content_offset + t.min_content_offset << "\n"
|
||||||
<< " content_length: "
|
<< " content_length: "
|
||||||
<< pe.delta_content_length + t.min_content_length << std::endl
|
<< pe.delta_content_length + t.min_content_length << "\n"
|
||||||
<< " nshared_objects: " << pe.nshared_objects << std::endl;
|
<< " nshared_objects: " << pe.nshared_objects << "\n";
|
||||||
for (size_t i2 = 0; i2 < toS(pe.nshared_objects); ++i2) {
|
for (size_t i2 = 0; i2 < toS(pe.nshared_objects); ++i2) {
|
||||||
*this->m->out_stream << " identifier " << i2 << ": "
|
*this->m->log->getInfo() << " identifier " << i2 << ": "
|
||||||
<< pe.shared_identifiers.at(i2) << std::endl;
|
<< pe.shared_identifiers.at(i2) << "\n";
|
||||||
*this->m->out_stream << " numerator " << i2 << ": "
|
*this->m->log->getInfo() << " numerator " << i2 << ": "
|
||||||
<< pe.shared_numerators.at(i2) << std::endl;
|
<< pe.shared_numerators.at(i2) << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1110,33 +1105,30 @@ void
|
|||||||
QPDF::dumpHSharedObject()
|
QPDF::dumpHSharedObject()
|
||||||
{
|
{
|
||||||
HSharedObject& t = this->m->shared_object_hints;
|
HSharedObject& t = this->m->shared_object_hints;
|
||||||
*this->m->out_stream << "first_shared_obj: " << t.first_shared_obj
|
*this->m->log->getInfo()
|
||||||
<< std::endl
|
<< "first_shared_obj: " << t.first_shared_obj << "\n"
|
||||||
<< "first_shared_offset: "
|
<< "first_shared_offset: " << adjusted_offset(t.first_shared_offset)
|
||||||
<< adjusted_offset(t.first_shared_offset) << std::endl
|
<< "\n"
|
||||||
<< "nshared_first_page: " << t.nshared_first_page
|
<< "nshared_first_page: " << t.nshared_first_page << "\n"
|
||||||
<< std::endl
|
<< "nshared_total: " << t.nshared_total << "\n"
|
||||||
<< "nshared_total: " << t.nshared_total << std::endl
|
<< "nbits_nobjects: " << t.nbits_nobjects << "\n"
|
||||||
<< "nbits_nobjects: " << t.nbits_nobjects << std::endl
|
<< "min_group_length: " << t.min_group_length << "\n"
|
||||||
<< "min_group_length: " << t.min_group_length
|
<< "nbits_delta_group_length: " << t.nbits_delta_group_length << "\n";
|
||||||
<< std::endl
|
|
||||||
<< "nbits_delta_group_length: "
|
|
||||||
<< t.nbits_delta_group_length << std::endl;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < toS(t.nshared_total); ++i) {
|
for (size_t i = 0; i < toS(t.nshared_total); ++i) {
|
||||||
HSharedObjectEntry& se = t.entries.at(i);
|
HSharedObjectEntry& se = t.entries.at(i);
|
||||||
*this->m->out_stream
|
*this->m->log->getInfo()
|
||||||
<< "Shared Object " << i << ":" << std::endl
|
<< "Shared Object " << i << ":\n"
|
||||||
<< " group length: " << se.delta_group_length + t.min_group_length
|
<< " group length: " << se.delta_group_length + t.min_group_length
|
||||||
<< std::endl;
|
<< "\n";
|
||||||
// PDF spec says signature present nobjects_minus_one are
|
// PDF spec says signature present nobjects_minus_one are
|
||||||
// always 0, so print them only if they have a non-zero value.
|
// always 0, so print them only if they have a non-zero value.
|
||||||
if (se.signature_present) {
|
if (se.signature_present) {
|
||||||
*this->m->out_stream << " signature present" << std::endl;
|
*this->m->log->getInfo() << " signature present\n";
|
||||||
}
|
}
|
||||||
if (se.nobjects_minus_one != 0) {
|
if (se.nobjects_minus_one != 0) {
|
||||||
*this->m->out_stream << " nobjects: " << se.nobjects_minus_one + 1
|
*this->m->log->getInfo()
|
||||||
<< std::endl;
|
<< " nobjects: " << se.nobjects_minus_one + 1 << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1144,11 +1136,12 @@ QPDF::dumpHSharedObject()
|
|||||||
void
|
void
|
||||||
QPDF::dumpHGeneric(HGeneric& t)
|
QPDF::dumpHGeneric(HGeneric& t)
|
||||||
{
|
{
|
||||||
*this->m->out_stream << "first_object: " << t.first_object << std::endl
|
*this->m->log->getInfo()
|
||||||
<< "first_object_offset: "
|
<< "first_object: " << t.first_object << "\n"
|
||||||
<< adjusted_offset(t.first_object_offset) << std::endl
|
<< "first_object_offset: " << adjusted_offset(t.first_object_offset)
|
||||||
<< "nobjects: " << t.nobjects << std::endl
|
<< "\n"
|
||||||
<< "group_length: " << t.group_length << std::endl;
|
<< "nobjects: " << t.nobjects << "\n"
|
||||||
|
<< "group_length: " << t.group_length << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
|
@ -103,6 +103,10 @@ For a detailed list of changes, please see the file
|
|||||||
``QPDFNumberTreeObjectHelper`` constructors that don't take a
|
``QPDFNumberTreeObjectHelper`` constructors that don't take a
|
||||||
``QPDF&`` argument.
|
``QPDF&`` argument.
|
||||||
|
|
||||||
|
- The function passed to and called by ``QPDFJob::doIfVerbose``
|
||||||
|
now takes a ``Pipeline&` argument instead of a ``std::ostream&``
|
||||||
|
argument.
|
||||||
|
|
||||||
- Intentionally break API to call attention to operations that
|
- Intentionally break API to call attention to operations that
|
||||||
write files with insecure encryption:
|
write files with insecure encryption:
|
||||||
|
|
||||||
|
@ -570,7 +570,17 @@ test_11(QPDF& pdf, char const* arg2)
|
|||||||
static void
|
static void
|
||||||
test_12(QPDF& pdf, char const* arg2)
|
test_12(QPDF& pdf, char const* arg2)
|
||||||
{
|
{
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
pdf.setOutputStreams(0, 0);
|
pdf.setOutputStreams(0, 0);
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
pdf.showLinearizationData();
|
pdf.showLinearizationData();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,7 +589,17 @@ test_13(QPDF& pdf, char const* arg2)
|
|||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
pdf.setOutputStreams(&out, &err);
|
pdf.setOutputStreams(&out, &err);
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
pdf.showLinearizationData();
|
pdf.showLinearizationData();
|
||||||
std::cout << "---output---" << std::endl
|
std::cout << "---output---" << std::endl
|
||||||
<< out.str() << "---error---" << std::endl
|
<< out.str() << "---error---" << std::endl
|
||||||
@ -2951,7 +2971,17 @@ test_84(QPDF& pdf, char const* arg2)
|
|||||||
std::ostringstream cerr;
|
std::ostringstream cerr;
|
||||||
{
|
{
|
||||||
QPDFJob j;
|
QPDFJob j;
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma warning(disable : 4996)
|
||||||
|
#endif
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
j.setOutputStreams(&cout, &cerr);
|
j.setOutputStreams(&cout, &cerr);
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__))
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
j.config()
|
j.config()
|
||||||
->inputFile("bad2.pdf")
|
->inputFile("bad2.pdf")
|
||||||
->showObject("4,0")
|
->showObject("4,0")
|
||||||
|
Loading…
Reference in New Issue
Block a user