mirror of
https://github.com/qpdf/qpdf.git
synced 2024-05-31 01:10:51 +00:00
QPDFJob increment: get rid of exit, handle verbose
Remove all calls to exit() from QPDFJob. Handle code that runs in verbose mode to enable it to make use of output streams and message prefix (whoami) from QPDFJob. This removes temporarily duplicated exit code logic and most access to whoami/std::cout outside of QPDFJob proper.
This commit is contained in:
parent
0910e767ad
commit
1ddf5b4b4b
|
@ -33,6 +33,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
class QPDFWriter;
|
class QPDFWriter;
|
||||||
|
|
||||||
|
@ -42,9 +43,23 @@ class QPDFJob
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFJob();
|
QPDFJob();
|
||||||
|
|
||||||
|
// Set name that is used to prefix verbose messages, progress
|
||||||
|
// messages, and other things that the library writes to output
|
||||||
|
// and error streams on the caller's behalf. Defaults to "qpdf".
|
||||||
|
QPDF_DLL
|
||||||
|
void setMessagePrefix(std::string const&);
|
||||||
|
|
||||||
|
// Override streams that errors and output go to. Defaults are
|
||||||
|
// std::cout and std::cerr.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||||
|
|
||||||
|
// If in verbose mode, call the given function, passing in the
|
||||||
|
// output stream and message prefix.
|
||||||
|
QPDF_DLL
|
||||||
|
void doIfVerbose(
|
||||||
|
std::function<void(std::ostream&, std::string const& prefix)> fn);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
@ -63,14 +78,13 @@ class QPDFJob
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool checkIsEncrypted();
|
bool checkIsEncrypted();
|
||||||
|
|
||||||
|
|
||||||
// Return value is bitwise OR of values from qpdf_encryption_status_e
|
// Return value is bitwise OR of values from qpdf_encryption_status_e
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
unsigned long getEncryptionStatus();
|
unsigned long getEncryptionStatus();
|
||||||
|
|
||||||
// QXXXQ From here to END-PUBLIC should all be private
|
// QXXXQ From here to END-PUBLIC should all be private or
|
||||||
|
// different somehow
|
||||||
public:
|
public:
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static JSON json_schema(std::set<std::string>* keys = 0);
|
static JSON json_schema(std::set<std::string>* keys = 0);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
@ -165,6 +179,10 @@ class QPDFJob
|
||||||
void setWriterOptions(QPDF& pdf, QPDFWriter& w);
|
void setWriterOptions(QPDF& pdf, QPDFWriter& w);
|
||||||
void doSplitPages(QPDF& pdf, bool& warnings);
|
void doSplitPages(QPDF& pdf, bool& warnings);
|
||||||
void writeOutfile(QPDF& pdf);
|
void writeOutfile(QPDF& pdf);
|
||||||
|
void doJSON(QPDF& pdf);
|
||||||
|
void doInspection(QPDF& pdf);
|
||||||
|
void showEncryption(QPDF& pdf);
|
||||||
|
void doCheck(QPDF& pdf);
|
||||||
|
|
||||||
enum remove_unref_e { re_auto, re_yes, re_no };
|
enum remove_unref_e { re_auto, re_yes, re_no };
|
||||||
|
|
||||||
|
@ -295,6 +313,7 @@ class QPDFJob
|
||||||
Members();
|
Members();
|
||||||
Members(Members const&) = delete;
|
Members(Members const&) = delete;
|
||||||
|
|
||||||
|
std::string whoami;
|
||||||
bool warnings;
|
bool warnings;
|
||||||
bool creates_output;
|
bool creates_output;
|
||||||
std::ostream* out_stream;
|
std::ostream* out_stream;
|
||||||
|
|
|
@ -35,8 +35,6 @@
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
|
|
||||||
// QXXXQ temporary for compilation
|
// QXXXQ temporary for compilation
|
||||||
static int constexpr EXIT_ERROR = 2;
|
|
||||||
static int EXIT_WARNING = 3; // may be changed to 0 at runtime
|
|
||||||
static char const* whoami = "qpdf";
|
static char const* whoami = "qpdf";
|
||||||
// /QXXXQ
|
// /QXXXQ
|
||||||
|
|
||||||
|
@ -82,7 +80,8 @@ namespace
|
||||||
class ProgressReporter: public QPDFWriter::ProgressReporter
|
class ProgressReporter: public QPDFWriter::ProgressReporter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ProgressReporter(char const* filename) :
|
ProgressReporter(std::string const& whoami, char const* filename) :
|
||||||
|
whoami(whoami),
|
||||||
filename(filename)
|
filename(filename)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -92,6 +91,7 @@ namespace
|
||||||
|
|
||||||
virtual void reportProgress(int);
|
virtual void reportProgress(int);
|
||||||
private:
|
private:
|
||||||
|
std::string whoami;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,7 @@ ProgressReporter::reportProgress(int percentage)
|
||||||
|
|
||||||
|
|
||||||
QPDFJob::Members::Members() :
|
QPDFJob::Members::Members() :
|
||||||
|
whoami("qpdf"),
|
||||||
warnings(false),
|
warnings(false),
|
||||||
creates_output(false),
|
creates_output(false),
|
||||||
out_stream(&std::cout),
|
out_stream(&std::cout),
|
||||||
|
@ -244,6 +245,12 @@ QPDFJob::QPDFJob() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFJob::setMessagePrefix(std::string const& whoami)
|
||||||
|
{
|
||||||
|
this->m->whoami = whoami;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
|
QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
|
||||||
{
|
{
|
||||||
|
@ -251,6 +258,16 @@ QPDFJob::setOutputStreams(std::ostream* out, std::ostream* err)
|
||||||
this->m->err_stream = err ? err : &std::cerr;
|
this->m->err_stream = err ? err : &std::cerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFJob::doIfVerbose(
|
||||||
|
std::function<void(std::ostream&, std::string const& prefix)> fn)
|
||||||
|
{
|
||||||
|
if (this->verbose && (this->m->out_stream != nullptr))
|
||||||
|
{
|
||||||
|
fn(*(this->m->out_stream), this->m->whoami);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_version(std::string const& full_version_string,
|
static void parse_version(std::string const& full_version_string,
|
||||||
std::string& version, int& extension_level)
|
std::string& version, int& extension_level)
|
||||||
{
|
{
|
||||||
|
@ -316,8 +333,10 @@ static std::string show_encryption_method(QPDF::encryption_method_e method)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_encryption(QPDF& pdf, QPDFJob& o)
|
void
|
||||||
|
QPDFJob::showEncryption(QPDF& pdf)
|
||||||
{
|
{
|
||||||
|
QPDFJob& o = *this; // QXXXQ
|
||||||
// Extract /P from /Encrypt
|
// Extract /P from /Encrypt
|
||||||
int R = 0;
|
int R = 0;
|
||||||
int P = 0;
|
int P = 0;
|
||||||
|
@ -380,8 +399,10 @@ static void show_encryption(QPDF& pdf, QPDFJob& o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_check(QPDF& pdf, QPDFJob& o, int& exit_code)
|
void
|
||||||
|
QPDFJob::doCheck(QPDF& pdf)
|
||||||
{
|
{
|
||||||
|
QPDFJob& o = *this; // QXXXQ
|
||||||
// Code below may set okay to false but not to true.
|
// Code below may set okay to false but not to true.
|
||||||
// We assume okay until we prove otherwise but may
|
// We assume okay until we prove otherwise but may
|
||||||
// continue to perform additional checks after finding
|
// continue to perform additional checks after finding
|
||||||
|
@ -399,7 +420,7 @@ static void do_check(QPDF& pdf, QPDFJob& o, int& exit_code)
|
||||||
<< pdf.getExtensionLevel();
|
<< pdf.getExtensionLevel();
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
show_encryption(pdf, o);
|
showEncryption(pdf);
|
||||||
if (pdf.isLinearized())
|
if (pdf.isLinearized())
|
||||||
{
|
{
|
||||||
std::cout << "File is linearized\n";
|
std::cout << "File is linearized\n";
|
||||||
|
@ -443,8 +464,9 @@ static void do_check(QPDF& pdf, QPDFJob& o, int& exit_code)
|
||||||
catch (QPDFExc& e)
|
catch (QPDFExc& e)
|
||||||
{
|
{
|
||||||
okay = false;
|
okay = false;
|
||||||
std::cerr << "ERROR: page " << pageno << ": "
|
*(this->m->err_stream)
|
||||||
<< e.what() << std::endl;
|
<< "ERROR: page " << pageno << ": "
|
||||||
|
<< e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -453,28 +475,27 @@ static void do_check(QPDF& pdf, QPDFJob& o, int& exit_code)
|
||||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||||
okay = false;
|
okay = false;
|
||||||
}
|
}
|
||||||
if (okay)
|
if (! okay)
|
||||||
{
|
{
|
||||||
if ((! pdf.getWarnings().empty()) || warnings)
|
throw std::runtime_error("errors detected");
|
||||||
{
|
}
|
||||||
exit_code = EXIT_WARNING;
|
|
||||||
}
|
if ((! pdf.getWarnings().empty()) || warnings)
|
||||||
else
|
{
|
||||||
{
|
this->m->warnings = TRUE;
|
||||||
std::cout << "No syntax or stream encoding errors"
|
|
||||||
<< " found; the file may still contain"
|
|
||||||
<< std::endl
|
|
||||||
<< "errors that qpdf cannot detect"
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
exit_code = EXIT_ERROR;
|
*(this->m->out_stream)
|
||||||
|
<< "No syntax or stream encoding errors"
|
||||||
|
<< " found; the file may still contain"
|
||||||
|
<< std::endl
|
||||||
|
<< "errors that qpdf cannot detect"
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_show_obj(QPDF& pdf, QPDFJob& o, int& exit_code)
|
static void do_show_obj(QPDF& pdf, QPDFJob& o)
|
||||||
{
|
{
|
||||||
QPDFObjectHandle obj;
|
QPDFObjectHandle obj;
|
||||||
if (o.show_trailer)
|
if (o.show_trailer)
|
||||||
|
@ -485,6 +506,7 @@ static void do_show_obj(QPDF& pdf, QPDFJob& o, int& exit_code)
|
||||||
{
|
{
|
||||||
obj = pdf.getObjectByID(o.show_obj, o.show_gen);
|
obj = pdf.getObjectByID(o.show_obj, o.show_gen);
|
||||||
}
|
}
|
||||||
|
bool error = false;
|
||||||
if (obj.isStream())
|
if (obj.isStream())
|
||||||
{
|
{
|
||||||
if (o.show_raw_stream_data || o.show_filtered_stream_data)
|
if (o.show_raw_stream_data || o.show_filtered_stream_data)
|
||||||
|
@ -494,9 +516,8 @@ static void do_show_obj(QPDF& pdf, QPDFJob& o, int& exit_code)
|
||||||
(! obj.pipeStreamData(0, 0, qpdf_dl_all)))
|
(! obj.pipeStreamData(0, 0, qpdf_dl_all)))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf unable to filter");
|
QTC::TC("qpdf", "qpdf unable to filter");
|
||||||
std::cerr << "Unable to filter stream data."
|
obj.warnIfPossible("unable to filter stream data");
|
||||||
<< std::endl;
|
error = true;
|
||||||
exit_code = EXIT_ERROR;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -519,6 +540,11 @@ static void do_show_obj(QPDF& pdf, QPDFJob& o, int& exit_code)
|
||||||
{
|
{
|
||||||
std::cout << obj.unparseResolved() << std::endl;
|
std::cout << obj.unparseResolved() << std::endl;
|
||||||
}
|
}
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
"unable to get object " + obj.getObjGen().unparse());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_show_pages(QPDF& pdf, QPDFJob& o)
|
static void do_show_pages(QPDF& pdf, QPDFJob& o)
|
||||||
|
@ -581,29 +607,28 @@ static void do_list_attachments(QPDF& pdf, QPDFJob& o)
|
||||||
std::cout << key << " -> "
|
std::cout << key << " -> "
|
||||||
<< efoh->getEmbeddedFileStream().getObjGen()
|
<< efoh->getEmbeddedFileStream().getObjGen()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
|
||||||
auto desc = efoh->getDescription();
|
auto desc = efoh->getDescription();
|
||||||
if (! desc.empty())
|
if (! desc.empty())
|
||||||
{
|
{
|
||||||
std::cout << " description: " << desc << std::endl;
|
cout << " description: " << desc << std::endl;
|
||||||
}
|
}
|
||||||
std::cout << " preferred name: " << efoh->getFilename()
|
cout << " preferred name: " << efoh->getFilename()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << " all names:" << std::endl;
|
cout << " all names:" << std::endl;
|
||||||
for (auto const& i2: efoh->getFilenames())
|
for (auto const& i2: efoh->getFilenames())
|
||||||
{
|
{
|
||||||
std::cout << " " << i2.first << " -> " << i2.second
|
cout << " " << i2.first << " -> " << i2.second
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
std::cout << " all data streams:" << std::endl;
|
cout << " all data streams:" << std::endl;
|
||||||
for (auto i2: efoh->getEmbeddedFileStreams().ditems())
|
for (auto i2: efoh->getEmbeddedFileStreams().ditems())
|
||||||
{
|
{
|
||||||
std::cout << " " << i2.first << " -> "
|
cout << " " << i2.first << " -> "
|
||||||
<< i2.second.getObjGen()
|
<< i2.second.getObjGen()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -612,16 +637,14 @@ static void do_list_attachments(QPDF& pdf, QPDFJob& o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_show_attachment(QPDF& pdf, QPDFJob& o, int& exit_code)
|
static void do_show_attachment(QPDF& pdf, QPDFJob& o)
|
||||||
{
|
{
|
||||||
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
QPDFEmbeddedFileDocumentHelper efdh(pdf);
|
||||||
auto fs = efdh.getEmbeddedFile(o.attachment_to_show);
|
auto fs = efdh.getEmbeddedFile(o.attachment_to_show);
|
||||||
if (! fs)
|
if (! fs)
|
||||||
{
|
{
|
||||||
std::cerr << whoami << ": attachment " << o.attachment_to_show
|
throw std::runtime_error(
|
||||||
<< " not found" << std::endl;
|
"attachment " + o.attachment_to_show + " not found");
|
||||||
exit_code = EXIT_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
auto efs = fs->getEmbeddedFileStream();
|
auto efs = fs->getEmbeddedFileStream();
|
||||||
QUtil::binary_stdout();
|
QUtil::binary_stdout();
|
||||||
|
@ -1149,8 +1172,9 @@ QPDFJob::json_schema(std::set<std::string>* keys)
|
||||||
|
|
||||||
bool all_keys = ((keys == 0) || keys->empty());
|
bool all_keys = ((keys == 0) || keys->empty());
|
||||||
|
|
||||||
|
// QXXXQ
|
||||||
// The list of selectable top-level keys id duplicated in three
|
// The list of selectable top-level keys id duplicated in three
|
||||||
// places: json_schema, do_json, and initOptionTable.
|
// places: json_schema, doJSON, and initOptionTable.
|
||||||
if (all_keys || keys->count("objects"))
|
if (all_keys || keys->count("objects"))
|
||||||
{
|
{
|
||||||
schema.addDictionaryMember(
|
schema.addDictionaryMember(
|
||||||
|
@ -1456,8 +1480,10 @@ QPDFJob::json_schema(std::set<std::string>* keys)
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_json(QPDF& pdf, QPDFJob& o)
|
void
|
||||||
|
QPDFJob::doJSON(QPDF& pdf)
|
||||||
{
|
{
|
||||||
|
QPDFJob& o = *this; // QXXXQ
|
||||||
JSON j = JSON::makeDictionary();
|
JSON j = JSON::makeDictionary();
|
||||||
// This version is updated every time a non-backward-compatible
|
// This version is updated every time a non-backward-compatible
|
||||||
// change is made to the JSON format. Clients of the JSON are to
|
// change is made to the JSON format. Clients of the JSON are to
|
||||||
|
@ -1486,8 +1512,9 @@ static void do_json(QPDF& pdf, QPDFJob& o)
|
||||||
"decodelevel", JSON::makeString(decode_level_str));
|
"decodelevel", JSON::makeString(decode_level_str));
|
||||||
|
|
||||||
bool all_keys = o.json_keys.empty();
|
bool all_keys = o.json_keys.empty();
|
||||||
|
// QXXXQ
|
||||||
// The list of selectable top-level keys id duplicated in three
|
// The list of selectable top-level keys id duplicated in three
|
||||||
// places: json_schema, do_json, and initOptionTable.
|
// places: json_schema, doJSON, and initOptionTable.
|
||||||
if (all_keys || o.json_keys.count("objects"))
|
if (all_keys || o.json_keys.count("objects"))
|
||||||
{
|
{
|
||||||
do_json_objects(pdf, o, j);
|
do_json_objects(pdf, o, j);
|
||||||
|
@ -1527,9 +1554,9 @@ static void do_json(QPDF& pdf, QPDFJob& o)
|
||||||
std::list<std::string> errors;
|
std::list<std::string> errors;
|
||||||
if (! j.checkSchema(schema, errors))
|
if (! j.checkSchema(schema, errors))
|
||||||
{
|
{
|
||||||
std::cerr
|
*(this->m->err_stream)
|
||||||
<< whoami << " didn't create JSON that complies with its own\n\
|
<< "QPDFJob didn't create JSON that complies with its own rules.\n\
|
||||||
rules. 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\
|
||||||
ideally with the file that caused the error and the output below. Thanks!\n\
|
ideally with the file that caused the error and the output below. Thanks!\n\
|
||||||
\n";
|
\n";
|
||||||
|
@ -1543,16 +1570,17 @@ ideally with the file that caused the error and the output below. Thanks!\n\
|
||||||
std::cout << j.unparse() << std::endl;
|
std::cout << j.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_inspection(QPDF& pdf, QPDFJob& o)
|
void
|
||||||
|
QPDFJob::doInspection(QPDF& pdf)
|
||||||
{
|
{
|
||||||
int exit_code = 0;
|
QPDFJob& o = *this; // QXXXQ
|
||||||
if (o.check)
|
if (o.check)
|
||||||
{
|
{
|
||||||
do_check(pdf, o, exit_code);
|
doCheck(pdf);
|
||||||
}
|
}
|
||||||
if (o.json)
|
if (o.json)
|
||||||
{
|
{
|
||||||
do_json(pdf, o);
|
doJSON(pdf);
|
||||||
}
|
}
|
||||||
if (o.show_npages)
|
if (o.show_npages)
|
||||||
{
|
{
|
||||||
|
@ -1562,7 +1590,7 @@ static void do_inspection(QPDF& pdf, QPDFJob& o)
|
||||||
}
|
}
|
||||||
if (o.show_encryption)
|
if (o.show_encryption)
|
||||||
{
|
{
|
||||||
show_encryption(pdf, o);
|
showEncryption(pdf);
|
||||||
}
|
}
|
||||||
if (o.check_linearization)
|
if (o.check_linearization)
|
||||||
{
|
{
|
||||||
|
@ -1571,9 +1599,9 @@ static void do_inspection(QPDF& pdf, QPDFJob& o)
|
||||||
std::cout << o.infilename << ": no linearization errors"
|
std::cout << o.infilename << ": no linearization errors"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
else if (exit_code != EXIT_ERROR)
|
else
|
||||||
{
|
{
|
||||||
exit_code = EXIT_WARNING;
|
this->m->warnings = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (o.show_linearization)
|
if (o.show_linearization)
|
||||||
|
@ -1594,7 +1622,7 @@ static void do_inspection(QPDF& pdf, QPDFJob& o)
|
||||||
}
|
}
|
||||||
if ((o.show_obj > 0) || o.show_trailer)
|
if ((o.show_obj > 0) || o.show_trailer)
|
||||||
{
|
{
|
||||||
do_show_obj(pdf, o, exit_code);
|
do_show_obj(pdf, o);
|
||||||
}
|
}
|
||||||
if (o.show_pages)
|
if (o.show_pages)
|
||||||
{
|
{
|
||||||
|
@ -1606,17 +1634,11 @@ static void do_inspection(QPDF& pdf, QPDFJob& o)
|
||||||
}
|
}
|
||||||
if (! o.attachment_to_show.empty())
|
if (! o.attachment_to_show.empty())
|
||||||
{
|
{
|
||||||
do_show_attachment(pdf, o, exit_code);
|
do_show_attachment(pdf, o);
|
||||||
}
|
}
|
||||||
if ((! pdf.getWarnings().empty()) && (exit_code != EXIT_ERROR))
|
if (! pdf.getWarnings().empty())
|
||||||
{
|
{
|
||||||
std::cerr << whoami
|
this->m->warnings = true;
|
||||||
<< ": operation succeeded with warnings" << std::endl;
|
|
||||||
exit_code = EXIT_WARNING;
|
|
||||||
}
|
|
||||||
if (exit_code)
|
|
||||||
{
|
|
||||||
exit(exit_code); // QXXXQ
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,11 +1659,13 @@ 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 (o.verbose && (! description.empty()))
|
if (! description.empty())
|
||||||
{
|
{
|
||||||
std::cout << whoami << ": " << description
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
<< ": not optimizing because image dictionary"
|
cout << whoami << ": " << description
|
||||||
<< " is missing required keys" << std::endl;
|
<< ": not optimizing because image dictionary"
|
||||||
|
<< " is missing required keys" << std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1649,11 +1673,13 @@ 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", "qpdf image optimize bits per component");
|
QTC::TC("qpdf", "qpdf image optimize bits per component");
|
||||||
if (o.verbose && (! description.empty()))
|
if (! description.empty())
|
||||||
{
|
{
|
||||||
std::cout << whoami << ": " << description
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
<< ": not optimizing because image has other than"
|
cout << whoami << ": " << description
|
||||||
<< " 8 bits per component" << std::endl;
|
<< ": not optimizing because image has other than"
|
||||||
|
<< " 8 bits per component" << std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1700,11 +1726,13 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf image optimize colorspace");
|
QTC::TC("qpdf", "qpdf image optimize colorspace");
|
||||||
if (o.verbose && (! description.empty()))
|
if (! description.empty())
|
||||||
{
|
{
|
||||||
std::cout << whoami << ": " << description
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
<< ": not optimizing because qpdf can't optimize"
|
cout << whoami << ": " << description
|
||||||
<< " images with this colorspace" << std::endl;
|
<< ": not optimizing because qpdf can't optimize"
|
||||||
|
<< " images with this colorspace" << std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1713,12 +1741,14 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
|
||||||
((o.oi_min_area > 0) && ((w * h) <= o.oi_min_area)))
|
((o.oi_min_area > 0) && ((w * h) <= o.oi_min_area)))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf image optimize too small");
|
QTC::TC("qpdf", "qpdf image optimize too small");
|
||||||
if (o.verbose && (! description.empty()))
|
if (! description.empty())
|
||||||
{
|
{
|
||||||
std::cout << whoami << ": " << description
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
<< ": not optimizing because image"
|
cout << whoami << ": " << description
|
||||||
<< " is smaller than requested minimum dimensions"
|
<< ": not optimizing because image"
|
||||||
<< std::endl;
|
<< " is smaller than requested minimum dimensions"
|
||||||
|
<< std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1733,13 +1763,12 @@ 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");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": " << description
|
||||||
std::cout << whoami << ": " << 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;
|
});
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Pl_Discard d;
|
Pl_Discard d;
|
||||||
|
@ -1758,21 +1787,19 @@ 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");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": " << description
|
||||||
std::cout << whoami << ": " << 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;
|
||||||
}
|
}
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": " << description
|
||||||
std::cout << whoami << ": " << 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;
|
});
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1889,13 +1916,15 @@ static PointerHolder<QPDF> do_process(
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((! warned) && o.verbose)
|
if (! warned)
|
||||||
{
|
{
|
||||||
warned = true;
|
warned = true;
|
||||||
std::cout << whoami << ": supplied password didn't work;"
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
<< " trying other passwords based on interpreting"
|
cout << whoami << ": supplied password didn't work;"
|
||||||
<< " password with different string encodings"
|
<< " trying other passwords based on interpreting"
|
||||||
<< std::endl;
|
<< " password with different string encodings"
|
||||||
|
<< std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Should not be reachable
|
// Should not be reachable
|
||||||
|
@ -2032,10 +2061,9 @@ 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;
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << " " << uo.which << " " << from_pageno << std::endl;
|
||||||
std::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));
|
||||||
if (0 == fo.count(from_pageno))
|
if (0 == fo.count(from_pageno))
|
||||||
{
|
{
|
||||||
|
@ -2116,16 +2144,14 @@ 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();
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": processing underlay/overlay" << std::endl;
|
||||||
std::cout << whoami << ": processing underlay/overlay" << std::endl;
|
});
|
||||||
}
|
|
||||||
for (size_t i = 0; i < main_npages; ++i)
|
for (size_t i = 0; i < main_npages; ++i)
|
||||||
{
|
{
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << " page " << 1+i << std::endl;
|
||||||
std::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,
|
||||||
underlay_fo, upages, main_pages.at(i),
|
underlay_fo, upages, main_pages.at(i),
|
||||||
true);
|
true);
|
||||||
|
@ -2174,12 +2200,11 @@ QPDFJob::addAttachments(QPDF& pdf)
|
||||||
}
|
}
|
||||||
|
|
||||||
efdh.replaceEmbeddedFile(to_add.key, fs);
|
efdh.replaceEmbeddedFile(to_add.key, fs);
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": attached " << to_add.path
|
||||||
std::cout << whoami << ": 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;
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! duplicated_keys.empty())
|
if (! duplicated_keys.empty())
|
||||||
|
@ -2210,11 +2235,10 @@ 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)
|
||||||
{
|
{
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": copying attachments from "
|
||||||
std::cout << whoami << ": copying attachments from "
|
<< to_copy.path << std::endl;
|
||||||
<< to_copy.path << std::endl;
|
});
|
||||||
}
|
|
||||||
auto other = processFile(
|
auto other = processFile(
|
||||||
to_copy.path.c_str(), to_copy.password.c_str());
|
to_copy.path.c_str(), to_copy.password.c_str());
|
||||||
QPDFEmbeddedFileDocumentHelper other_efdh(*other);
|
QPDFEmbeddedFileDocumentHelper other_efdh(*other);
|
||||||
|
@ -2233,11 +2257,11 @@ QPDFJob::copyAttachments(QPDF& pdf)
|
||||||
iter.second->getObjectHandle());
|
iter.second->getObjectHandle());
|
||||||
efdh.replaceEmbeddedFile(
|
efdh.replaceEmbeddedFile(
|
||||||
new_key, QPDFFileSpecObjectHelper(new_fs_oh));
|
new_key, QPDFFileSpecObjectHelper(new_fs_oh));
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout,
|
||||||
{
|
std::string const& whoami) {
|
||||||
std::cout << " " << iter.first << " -> " << new_key
|
cout << " " << iter.first << " -> " << new_key
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2361,11 +2385,11 @@ QPDFJob::handleTransformations(QPDF& pdf)
|
||||||
{
|
{
|
||||||
if (efdh.removeEmbeddedFile(key))
|
if (efdh.removeEmbeddedFile(key))
|
||||||
{
|
{
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout,
|
||||||
{
|
std::string const& whoami) {
|
||||||
std::cout << whoami <<
|
cout << whoami <<
|
||||||
": removed attachment " << key << std::endl;
|
": removed attachment " << key << std::endl;
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2407,11 +2431,10 @@ 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
|
||||||
|
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": " << pdf.getFilename()
|
||||||
std::cout << whoami << ": " << pdf.getFilename()
|
<< ": checking for shared resources" << std::endl;
|
||||||
<< ": checking for shared resources" << std::endl;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
std::list<QPDFObjectHandle> queue;
|
std::list<QPDFObjectHandle> queue;
|
||||||
queue.push_back(pdf.getRoot().getKey("/Pages"));
|
queue.push_back(pdf.getRoot().getKey("/Pages"));
|
||||||
|
@ -2433,12 +2456,12 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
|
||||||
if (dict.hasKey("/Resources"))
|
if (dict.hasKey("/Resources"))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf found resources in non-leaf");
|
QTC::TC("qpdf", "qpdf found resources in non-leaf");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout,
|
||||||
{
|
std::string const& whoami) {
|
||||||
std::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;
|
||||||
}
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int n = kids.getArrayNItems();
|
int n = kids.getArrayNItems();
|
||||||
|
@ -2457,15 +2480,15 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
|
||||||
if (resources_seen.count(resources_og))
|
if (resources_seen.count(resources_og))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf found shared resources in leaf");
|
QTC::TC("qpdf", "qpdf found shared resources in leaf");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout,
|
||||||
{
|
std::string const& whoami) {
|
||||||
std::cout << " 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()
|
<< resources_og.getGen()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
resources_seen.insert(resources_og);
|
resources_seen.insert(resources_og);
|
||||||
|
@ -2479,15 +2502,15 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
|
||||||
if (resources_seen.count(xobject_og))
|
if (resources_seen.count(xobject_og))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf found shared xobject in leaf");
|
QTC::TC("qpdf", "qpdf found shared xobject in leaf");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout,
|
||||||
{
|
std::string const& whoami) {
|
||||||
std::cout << " 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.getObj() << " "
|
||||||
<< xobject_og.getGen()
|
<< xobject_og.getGen()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
resources_seen.insert(xobject_og);
|
resources_seen.insert(xobject_og);
|
||||||
|
@ -2512,10 +2535,9 @@ static bool should_remove_unreferenced_resources(QPDF& pdf, QPDFJob& o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": no shared resources found" << std::endl;
|
||||||
std::cout << whoami << ": no shared resources found" << std::endl;
|
});
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2570,20 +2592,18 @@ static void handle_page_specs(
|
||||||
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");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": selecting --keep-open-files=n"
|
||||||
std::cout << whoami << ": selecting --keep-open-files=n"
|
<< std::endl;
|
||||||
<< std::endl;
|
});
|
||||||
}
|
|
||||||
o.keep_files_open = false;
|
o.keep_files_open = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": selecting --keep-open-files=y"
|
||||||
std::cout << whoami << ": selecting --keep-open-files=y"
|
<< std::endl;
|
||||||
<< std::endl;
|
});
|
||||||
}
|
|
||||||
o.keep_files_open = true;
|
o.keep_files_open = true;
|
||||||
QTC::TC("qpdf", "qpdf don't disable keep files open");
|
QTC::TC("qpdf", "qpdf don't disable keep files open");
|
||||||
}
|
}
|
||||||
|
@ -2618,11 +2638,10 @@ 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;
|
||||||
}
|
}
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": processing "
|
||||||
std::cout << whoami << ": processing "
|
<< page_spec.filename << std::endl;
|
||||||
<< page_spec.filename << std::endl;
|
});
|
||||||
}
|
|
||||||
PointerHolder<InputSource> is;
|
PointerHolder<InputSource> is;
|
||||||
ClosedFileInputSource* cis = 0;
|
ClosedFileInputSource* cis = 0;
|
||||||
if (! o.keep_files_open)
|
if (! o.keep_files_open)
|
||||||
|
@ -2690,12 +2709,11 @@ 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.
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami
|
||||||
std::cout << whoami
|
<< ": removing unreferenced pages from primary input"
|
||||||
<< ": removing unreferenced pages from primary input"
|
<< std::endl;
|
||||||
<< std::endl;
|
});
|
||||||
}
|
|
||||||
QPDFPageDocumentHelper dh(pdf);
|
QPDFPageDocumentHelper dh(pdf);
|
||||||
std::vector<QPDFPageObjectHelper> orig_pages = dh.getAllPages();
|
std::vector<QPDFPageObjectHelper> orig_pages = dh.getAllPages();
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator iter =
|
for (std::vector<QPDFPageObjectHelper>::iterator iter =
|
||||||
|
@ -2765,11 +2783,10 @@ static void handle_page_specs(
|
||||||
{
|
{
|
||||||
any_page_labels = true;
|
any_page_labels = true;
|
||||||
}
|
}
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": adding pages from "
|
||||||
std::cout << whoami << ": 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 =
|
||||||
page_data.selected_pages.begin();
|
page_data.selected_pages.begin();
|
||||||
pageno_iter != page_data.selected_pages.end();
|
pageno_iter != page_data.selected_pages.end();
|
||||||
|
@ -3002,15 +3019,15 @@ static void maybe_fix_write_password(int R, QPDFJob& o, std::string& password)
|
||||||
if (QUtil::utf8_to_pdf_doc(password, encoded))
|
if (QUtil::utf8_to_pdf_doc(password, encoded))
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "qpdf auto-encode password");
|
QTC::TC("qpdf", "qpdf auto-encode password");
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout,
|
||||||
{
|
std::string const& whoami) {
|
||||||
std::cout
|
cout
|
||||||
<< whoami
|
<< whoami
|
||||||
<< ": 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" << std::endl;
|
<< " encryption" << std::endl;
|
||||||
}
|
});
|
||||||
password = encoded;
|
password = encoded;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3088,9 +3105,8 @@ static void set_encryption_options(QPDF& pdf, QPDFJob& o, QPDFWriter& w)
|
||||||
{
|
{
|
||||||
if (! o.allow_weak_crypto)
|
if (! o.allow_weak_crypto)
|
||||||
{
|
{
|
||||||
// Do not set exit code to EXIT_WARNING for this case as
|
// Do not set warnings = true for this case as this does
|
||||||
// this does not reflect a potential problem with the
|
// not reflect a potential problem with the input file.
|
||||||
// input file.
|
|
||||||
QTC::TC("qpdf", "qpdf weak crypto warning");
|
QTC::TC("qpdf", "qpdf weak crypto warning");
|
||||||
std::cerr
|
std::cerr
|
||||||
<< whoami
|
<< whoami
|
||||||
|
@ -3247,7 +3263,8 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w)
|
||||||
}
|
}
|
||||||
if (o.progress && o.outfilename)
|
if (o.progress && o.outfilename)
|
||||||
{
|
{
|
||||||
w.registerProgressReporter(new ProgressReporter(o.outfilename));
|
w.registerProgressReporter(
|
||||||
|
new ProgressReporter(this->m->whoami, o.outfilename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3355,18 +3372,15 @@ QPDFJob::doSplitPages(QPDF& pdf, bool& warnings)
|
||||||
std::string outfile = before + page_range + after;
|
std::string outfile = before + page_range + after;
|
||||||
if (QUtil::same_file(o.infilename, outfile.c_str()))
|
if (QUtil::same_file(o.infilename, outfile.c_str()))
|
||||||
{
|
{
|
||||||
std::cerr << whoami
|
throw std::runtime_error(
|
||||||
<< ": split pages would overwrite input file with "
|
"split pages would overwrite input file with " + outfile);
|
||||||
<< outfile << std::endl;
|
|
||||||
exit(EXIT_ERROR); // QXXXQ
|
|
||||||
}
|
}
|
||||||
QPDFWriter w(outpdf, outfile.c_str());
|
QPDFWriter w(outpdf, outfile.c_str());
|
||||||
setWriterOptions(outpdf, w);
|
setWriterOptions(outpdf, w);
|
||||||
w.write();
|
w.write();
|
||||||
if (o.verbose)
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
{
|
cout << whoami << ": wrote file " << outfile << std::endl;
|
||||||
std::cout << whoami << ": wrote file " << outfile << std::endl;
|
});
|
||||||
}
|
|
||||||
if (outpdf.anyWarnings())
|
if (outpdf.anyWarnings())
|
||||||
{
|
{
|
||||||
warnings = true;
|
warnings = true;
|
||||||
|
@ -3399,10 +3413,11 @@ QPDFJob::writeOutfile(QPDF& pdf)
|
||||||
setWriterOptions(pdf, w);
|
setWriterOptions(pdf, w);
|
||||||
w.write();
|
w.write();
|
||||||
}
|
}
|
||||||
if (o.verbose && o.outfilename)
|
if (o.outfilename)
|
||||||
{
|
{
|
||||||
std::cout << whoami << ": wrote file "
|
o.doIfVerbose([&](std::ostream& cout, std::string const& whoami) {
|
||||||
<< o.outfilename << std::endl;
|
cout << whoami << ": wrote file " << o.outfilename << std::endl;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (o.replace_input)
|
if (o.replace_input)
|
||||||
{
|
{
|
||||||
|
@ -3495,7 +3510,7 @@ QPDFJob::run()
|
||||||
this->m->creates_output = ((o.outfilename != nullptr) || o.replace_input);
|
this->m->creates_output = ((o.outfilename != nullptr) || o.replace_input);
|
||||||
if (! this->m->creates_output)
|
if (! this->m->creates_output)
|
||||||
{
|
{
|
||||||
do_inspection(pdf, o);
|
doInspection(pdf);
|
||||||
}
|
}
|
||||||
else if (o.split_pages)
|
else if (o.split_pages)
|
||||||
{
|
{
|
||||||
|
|
19
qpdf/qpdf.cc
19
qpdf/qpdf.cc
|
@ -314,6 +314,7 @@ ArgParser::initOptionTable()
|
||||||
this->ap.addBare("show-pages", b(&ArgParser::argShowPages));
|
this->ap.addBare("show-pages", b(&ArgParser::argShowPages));
|
||||||
this->ap.addBare("with-images", b(&ArgParser::argWithImages));
|
this->ap.addBare("with-images", b(&ArgParser::argWithImages));
|
||||||
this->ap.addBare("json", b(&ArgParser::argJson));
|
this->ap.addBare("json", b(&ArgParser::argJson));
|
||||||
|
// QXXXQ
|
||||||
// The list of selectable top-level keys id duplicated in three
|
// The list of selectable top-level keys id duplicated in three
|
||||||
// places: json_schema, do_json, and initOptionTable.
|
// places: json_schema, do_json, and initOptionTable.
|
||||||
char const* json_key_choices[] = {
|
char const* json_key_choices[] = {
|
||||||
|
@ -2350,6 +2351,7 @@ ArgParser::doFinalChecks()
|
||||||
}
|
}
|
||||||
if (o.optimize_images && (! o.keep_inline_images))
|
if (o.optimize_images && (! o.keep_inline_images))
|
||||||
{
|
{
|
||||||
|
// QXXXQ this is not a check and doesn't belong here
|
||||||
o.externalize_inline_images = true;
|
o.externalize_inline_images = true;
|
||||||
}
|
}
|
||||||
if (o.check_requires_password && o.check_is_encrypted)
|
if (o.check_requires_password && o.check_is_encrypted)
|
||||||
|
@ -2384,7 +2386,7 @@ ArgParser::doFinalChecks()
|
||||||
usage("--split-pages may not be used when"
|
usage("--split-pages may not be used when"
|
||||||
" writing to standard output");
|
" writing to standard output");
|
||||||
}
|
}
|
||||||
if (o.verbose)
|
if (o.verbose) // QXXXQ
|
||||||
{
|
{
|
||||||
usage("--verbose may not be used when"
|
usage("--verbose may not be used when"
|
||||||
" writing to standard output");
|
" writing to standard output");
|
||||||
|
@ -2418,6 +2420,7 @@ int realmain(int argc, char* argv[])
|
||||||
// ArgParser must stay in scope for the duration of qpdf's run as
|
// ArgParser must stay in scope for the duration of qpdf's run as
|
||||||
// it holds dynamic memory used for argv.
|
// it holds dynamic memory used for argv.
|
||||||
QPDFJob j;
|
QPDFJob j;
|
||||||
|
j.setMessagePrefix(whoami);
|
||||||
ArgParser ap(argc, argv, j);
|
ArgParser ap(argc, argv, j);
|
||||||
|
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
|
@ -2439,9 +2442,17 @@ int realmain(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if (! j.suppressWarnings())
|
if (! j.suppressWarnings())
|
||||||
{
|
{
|
||||||
std::cerr << whoami << ": operation succeeded with warnings;"
|
if (j.createsOutput())
|
||||||
<< " resulting file may have some problems"
|
{
|
||||||
<< std::endl;
|
std::cerr << whoami << ": operation succeeded with warnings;"
|
||||||
|
<< " resulting file may have some problems"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << whoami << ": operation succeeded with warnings"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Still return with warning code even if warnings were
|
// Still return with warning code even if warnings were
|
||||||
// suppressed, so leave warnings == true.
|
// suppressed, so leave warnings == true.
|
||||||
|
|
|
@ -5,3 +5,4 @@ checking append-page-content-damaged.pdf
|
||||||
PDF Version: 1.3
|
PDF Version: 1.3
|
||||||
File is not encrypted
|
File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -4,3 +4,4 @@ File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
WARNING: bad-jpeg.pdf (offset 735): error decoding stream data for object 6 0: Not a JPEG file: starts with 0x77 0x77
|
WARNING: bad-jpeg.pdf (offset 735): error decoding stream data for object 6 0: Not a JPEG file: starts with 0x77 0x77
|
||||||
WARNING: bad-jpeg.pdf (offset 735): stream will be re-processed without filtering to avoid data loss
|
WARNING: bad-jpeg.pdf (offset 735): stream will be re-processed without filtering to avoid data loss
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -12,3 +12,4 @@ WARNING: bad-xref-entry.pdf: Attempting to reconstruct cross-reference table
|
||||||
5/0: uncompressed; offset = 583
|
5/0: uncompressed; offset = 583
|
||||||
6/0: uncompressed; offset = 629
|
6/0: uncompressed; offset = 629
|
||||||
7/0: uncompressed; offset = 774
|
7/0: uncompressed; offset = 774
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -5,3 +5,4 @@ File is not linearized
|
||||||
WARNING: page object 3 0 stream 7 0 (content, offset 52): parse error while reading object
|
WARNING: page object 3 0 stream 7 0 (content, offset 52): parse error while reading object
|
||||||
WARNING: page object 5 0 stream 15 0 (stream data, offset 117): EOF found while reading inline image
|
WARNING: page object 5 0 stream 15 0 (stream data, offset 117): EOF found while reading inline image
|
||||||
WARNING: page object 6 0 stream 19 0 (content, offset 53): parse error while reading object
|
WARNING: page object 6 0 stream 19 0 (content, offset 53): parse error while reading object
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -4,3 +4,4 @@ File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
WARNING: damaged-stream.pdf (offset 426): error decoding stream data for object 5 0: LZWDecoder: bad code received
|
WARNING: damaged-stream.pdf (offset 426): error decoding stream data for object 5 0: LZWDecoder: bad code received
|
||||||
WARNING: damaged-stream.pdf (offset 426): stream will be re-processed without filtering to avoid data loss
|
WARNING: damaged-stream.pdf (offset 426): stream will be re-processed without filtering to avoid data loss
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -3,3 +3,4 @@ PDF Version: 1.3
|
||||||
File is not encrypted
|
File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
WARNING: eof-reading-token.pdf object stream 12 (object 13 0, offset 5): EOF while reading token
|
WARNING: eof-reading-token.pdf object stream 12 (object 13 0, offset 5): EOF while reading token
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -5,3 +5,4 @@ WARNING: indirect-r-arg.pdf (object 1 0, offset 62): expected dictionary key but
|
||||||
PDF Version: 1.3
|
PDF Version: 1.3
|
||||||
File is not encrypted
|
File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -15,3 +15,4 @@ modify annotations: allowed
|
||||||
modify other: not allowed
|
modify other: not allowed
|
||||||
modify anything: not allowed
|
modify anything: not allowed
|
||||||
File is not linearized
|
File is not linearized
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -6,3 +6,4 @@ WARNING: linearization-bounds-1.pdf (linearization hint stream: object 62 0, off
|
||||||
WARNING: linearization-bounds-1.pdf (linearization hint stream: object 62 0, offset 1183): attempting to recover stream length
|
WARNING: linearization-bounds-1.pdf (linearization hint stream: object 62 0, offset 1183): attempting to recover stream length
|
||||||
WARNING: linearization-bounds-1.pdf (linearization hint stream: object 62 0, offset 1183): recovered stream length: 106
|
WARNING: linearization-bounds-1.pdf (linearization hint stream: object 62 0, offset 1183): recovered stream length: 106
|
||||||
WARNING: error encountered while checking linearization data: linearization-bounds-1.pdf (linearization hint table, offset 1183): /S (shared object) offset is out of bounds
|
WARNING: error encountered while checking linearization data: linearization-bounds-1.pdf (linearization hint table, offset 1183): /S (shared object) offset is out of bounds
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -6,3 +6,4 @@ WARNING: linearization-bounds-2.pdf (linearization hint stream: object 62 0, off
|
||||||
WARNING: linearization-bounds-2.pdf (linearization hint stream: object 62 0, offset 1183): attempting to recover stream length
|
WARNING: linearization-bounds-2.pdf (linearization hint stream: object 62 0, offset 1183): attempting to recover stream length
|
||||||
WARNING: linearization-bounds-2.pdf (linearization hint stream: object 62 0, offset 1183): recovered stream length: 106
|
WARNING: linearization-bounds-2.pdf (linearization hint stream: object 62 0, offset 1183): recovered stream length: 106
|
||||||
WARNING: error encountered while checking linearization data: linearization-bounds-2.pdf (linearization hint table, offset 1183): /S (shared object) offset is out of bounds
|
WARNING: error encountered while checking linearization data: linearization-bounds-2.pdf (linearization hint table, offset 1183): /S (shared object) offset is out of bounds
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -6,3 +6,4 @@ WARNING: linearization-large-vector-alloc.pdf (linearization hint stream: object
|
||||||
WARNING: linearization-large-vector-alloc.pdf (linearization hint stream: object 62 0, offset 1183): attempting to recover stream length
|
WARNING: linearization-large-vector-alloc.pdf (linearization hint stream: object 62 0, offset 1183): attempting to recover stream length
|
||||||
WARNING: linearization-large-vector-alloc.pdf (linearization hint stream: object 62 0, offset 1183): recovered stream length: 106
|
WARNING: linearization-large-vector-alloc.pdf (linearization hint stream: object 62 0, offset 1183): recovered stream length: 106
|
||||||
WARNING: error encountered while checking linearization data: overflow reading bit stream: wanted = 12556; available = 968
|
WARNING: error encountered while checking linearization data: overflow reading bit stream: wanted = 12556; available = 968
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -6,3 +6,4 @@ WARNING: name-pound-images.pdf (object 3 0, offset 471): name with stray # will
|
||||||
WARNING: name-pound-images.pdf (object 3 0, offset 508): name with stray # will not work with PDF >= 1.2
|
WARNING: name-pound-images.pdf (object 3 0, offset 508): name with stray # will not work with PDF >= 1.2
|
||||||
WARNING: page object 3 0 stream 4 0 (content, offset 59): name with stray # will not work with PDF >= 1.2
|
WARNING: page object 3 0 stream 4 0 (content, offset 59): name with stray # will not work with PDF >= 1.2
|
||||||
WARNING: page object 3 0 stream 4 0 (content, offset 131): name with stray # will not work with PDF >= 1.2
|
WARNING: page object 3 0 stream 4 0 (content, offset 131): name with stray # will not work with PDF >= 1.2
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -4,3 +4,4 @@ File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
WARNING: no-pages-types.pdf (page tree node, offset 307): /Type key should be /Page but is not; overriding
|
WARNING: no-pages-types.pdf (page tree node, offset 307): /Type key should be /Page but is not; overriding
|
||||||
WARNING: no-pages-types.pdf (page tree node, offset 307): /Type key should be /Pages but is not; overriding
|
WARNING: no-pages-types.pdf (page tree node, offset 307): /Type key should be /Pages but is not; overriding
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -5,3 +5,4 @@ WARNING: obj0.pdf: Attempting to reconstruct cross-reference table
|
||||||
PDF Version: 1.3
|
PDF Version: 1.3
|
||||||
File is not encrypted
|
File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -3,3 +3,4 @@ PDF Version: 1.3
|
||||||
File is not encrypted
|
File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
ERROR: pages-loop.pdf (object 3 0): Loop detected in /Pages structure (getAllPages)
|
ERROR: pages-loop.pdf (object 3 0): Loop detected in /Pages structure (getAllPages)
|
||||||
|
qpdf: errors detected
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
Unable to filter stream data.
|
WARNING: unfilterable.pdf, stream object 4 0: unable to filter stream data
|
||||||
|
qpdf: unable to get object 4,0
|
||||||
|
|
|
@ -7,3 +7,4 @@ WARNING: split-content-stream-errors.pdf (offset 557): stream will be re-process
|
||||||
WARNING: page object 3 0 (item index 0 (from 0)): ignoring non-stream in an array of streams
|
WARNING: page object 3 0 (item index 0 (from 0)): ignoring non-stream in an array of streams
|
||||||
WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received
|
WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received
|
||||||
ERROR: page 1: content stream (content stream object 6 0): errors while decoding content stream
|
ERROR: page 1: content stream (content stream object 6 0): errors while decoding content stream
|
||||||
|
qpdf: errors detected
|
||||||
|
|
|
@ -13,3 +13,4 @@ File is not linearized
|
||||||
4/0: uncompressed; offset = 307
|
4/0: uncompressed; offset = 307
|
||||||
5/0: uncompressed; offset = 403
|
5/0: uncompressed; offset = 403
|
||||||
6/0: uncompressed; offset = 438
|
6/0: uncompressed; offset = 438
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
|
@ -3,3 +3,4 @@ PDF Version: 1.3
|
||||||
File is not encrypted
|
File is not encrypted
|
||||||
File is not linearized
|
File is not linearized
|
||||||
WARNING: zero-offset.pdf (object 6 0): object has offset 0
|
WARNING: zero-offset.pdf (object 6 0): object has offset 0
|
||||||
|
qpdf: operation succeeded with warnings
|
||||||
|
|
Loading…
Reference in New Issue
Block a user