mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Rerun clang-format
This commit is contained in:
parent
6b077332d3
commit
60965d5f4d
@ -71,8 +71,7 @@ process(
|
||||
|
||||
// Create a file spec.
|
||||
std::string key = QUtil::path_basename(attachment);
|
||||
std::cout << whoami << ": attaching " << attachment << " as " << key
|
||||
<< std::endl;
|
||||
std::cout << whoami << ": attaching " << attachment << " as " << key << std::endl;
|
||||
auto fs = QPDFFileSpecObjectHelper::createFileSpec(q, key, attachment);
|
||||
|
||||
if (mimetype) {
|
||||
|
@ -23,15 +23,11 @@ static std::map<QPDFObjGen, int> page_map;
|
||||
void
|
||||
usage()
|
||||
{
|
||||
std::cerr
|
||||
<< "Usage: " << whoami << " [options] file.pdf [password]" << std::endl
|
||||
std::cerr << "Usage: " << whoami << " [options] file.pdf [password]" << std::endl
|
||||
<< "Options:" << std::endl
|
||||
<< " --numbers give bookmarks outline-style numbers"
|
||||
<< std::endl
|
||||
<< " --lines draw lines to show bookmark hierarchy"
|
||||
<< std::endl
|
||||
<< " --show-open indicate whether a bookmark is initially open"
|
||||
<< std::endl
|
||||
<< " --numbers give bookmarks outline-style numbers" << std::endl
|
||||
<< " --lines draw lines to show bookmark hierarchy" << std::endl
|
||||
<< " --show-open indicate whether a bookmark is initially open" << std::endl
|
||||
<< " --show-targets show target if possible" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
@ -120,16 +116,14 @@ show_bookmark_details(QPDFOutlineObjectHelper outline, std::vector<int> numbers)
|
||||
}
|
||||
|
||||
void
|
||||
extract_bookmarks(
|
||||
std::vector<QPDFOutlineObjectHelper> outlines, std::vector<int>& numbers)
|
||||
extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines, std::vector<int>& numbers)
|
||||
{
|
||||
// For style == st_numbers, numbers.at(n) contains the numerical
|
||||
// label for the outline, so we count up from 1.
|
||||
// For style == st_lines, numbers.at(n) == 0 indicates the last
|
||||
// outline at level n, and we don't otherwise care what the value
|
||||
// is, so we count up to zero.
|
||||
numbers.push_back(
|
||||
(style == st_lines) ? -QIntC::to_int(outlines.size()) : 0);
|
||||
numbers.push_back((style == st_lines) ? -QIntC::to_int(outlines.size()) : 0);
|
||||
for (auto& outline: outlines) {
|
||||
++(numbers.back());
|
||||
show_bookmark_details(outline, numbers);
|
||||
@ -196,8 +190,7 @@ main(int argc, char* argv[])
|
||||
std::cout << filename << " has no bookmarks" << std::endl;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << whoami << " processing file " << filename << ": "
|
||||
<< e.what() << std::endl;
|
||||
std::cerr << whoami << " processing file " << filename << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,7 @@ modify_file(qpdf_data qpdf)
|
||||
qpdf_oh_remove_key(qpdf, root, "/OpenAction");
|
||||
/* 0 is never a valid qpdf_oh */
|
||||
qpdf_oh pagemode = 0;
|
||||
if (qpdf_oh_is_dictionary(
|
||||
qpdf, qpdf_oh_get_key(qpdf, root, "/PageLabels"))) {
|
||||
if (qpdf_oh_is_dictionary(qpdf, qpdf_oh_get_key(qpdf, root, "/PageLabels"))) {
|
||||
pagemode = qpdf_oh_new_name(qpdf, "/UseOutlines");
|
||||
} else {
|
||||
pagemode = qpdf_oh_new_null(qpdf);
|
||||
@ -71,8 +70,7 @@ main(int argc, char* argv[])
|
||||
password = argv[2];
|
||||
outfile = argv[3];
|
||||
|
||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
||||
modify_file(qpdf) &&
|
||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) && modify_file(qpdf) &&
|
||||
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0)) {
|
||||
/* Use static ID for testing only. For production, a
|
||||
* non-static ID is used. See also
|
||||
@ -82,15 +80,11 @@ main(int argc, char* argv[])
|
||||
}
|
||||
while (qpdf_more_warnings(qpdf)) {
|
||||
warnings = 1;
|
||||
printf(
|
||||
"warning: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
printf("warning: %s\n", qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
}
|
||||
if (qpdf_has_error(qpdf)) {
|
||||
errors = 1;
|
||||
printf(
|
||||
"error: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
printf("error: %s\n", qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
}
|
||||
qpdf_cleanup(&qpdf);
|
||||
if (errors) {
|
||||
|
@ -97,8 +97,7 @@ main(int argc, char* argv[])
|
||||
page.filterContents(&counter, &out);
|
||||
std::cout << "\n% end " << pageno << std::endl;
|
||||
}
|
||||
std::cout << "Page " << pageno
|
||||
<< ": strings = " << counter.getCount() << std::endl;
|
||||
std::cout << "Page " << pageno << ": strings = " << counter.getCount() << std::endl;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
|
@ -41,8 +41,7 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
||||
J_COLOR_SPACE j_color_space;
|
||||
};
|
||||
|
||||
ImageProvider::ImageProvider(
|
||||
std::string const& color_space, std::string const& filter) :
|
||||
ImageProvider::ImageProvider(std::string const& color_space, std::string const& filter) :
|
||||
width(400),
|
||||
stripe_height(80),
|
||||
color_space(color_space),
|
||||
@ -107,8 +106,7 @@ ImageProvider::provideStreamData(QPDFObjGen const&, Pipeline* pipeline)
|
||||
to_delete.push_back(p_new);
|
||||
p = p_new.get();
|
||||
} else if (filter == "/RunLengthDecode") {
|
||||
p_new = std::make_shared<Pl_RunLength>(
|
||||
"image encoder", pipeline, Pl_RunLength::a_encode);
|
||||
p_new = std::make_shared<Pl_RunLength>("image encoder", pipeline, Pl_RunLength::a_encode);
|
||||
to_delete.push_back(p_new);
|
||||
p = p_new.get();
|
||||
}
|
||||
@ -184,8 +182,7 @@ add_page(
|
||||
image.replaceDict(image_dict);
|
||||
|
||||
// Provide the stream data.
|
||||
image.replaceStreamData(
|
||||
provider, QPDFObjectHandle::parse(filter), QPDFObjectHandle::newNull());
|
||||
image.replaceStreamData(provider, QPDFObjectHandle::parse(filter), QPDFObjectHandle::newNull());
|
||||
|
||||
// Create direct objects as needed by the page dictionary.
|
||||
QPDFObjectHandle procset = "[/PDF /Text /ImageC]"_qpdf;
|
||||
@ -202,8 +199,7 @@ add_page(
|
||||
resources.replaceKey("/XObject", xobject);
|
||||
|
||||
// Create the page content stream
|
||||
QPDFObjectHandle contents =
|
||||
createPageContents(pdf, color_space + " with filter " + filter);
|
||||
QPDFObjectHandle contents = createPageContents(pdf, color_space + " with filter " + filter);
|
||||
|
||||
// Create the page dictionary
|
||||
QPDFObjectHandle page = pdf.makeIndirectObject("<<"
|
||||
@ -256,8 +252,7 @@ check(
|
||||
}
|
||||
|
||||
// Check filter and color space.
|
||||
std::string desired_color_space =
|
||||
color_spaces[(pageno - 1) / n_color_spaces];
|
||||
std::string desired_color_space = color_spaces[(pageno - 1) / n_color_spaces];
|
||||
std::string desired_filter = filters[(pageno - 1) % n_filters];
|
||||
// In the default mode, QPDFWriter will compress with
|
||||
// /FlateDecode if no filters are provided.
|
||||
@ -271,16 +266,13 @@ check(
|
||||
bool this_errors = false;
|
||||
if (!filter.isNameAndEquals(desired_filter)) {
|
||||
this_errors = errors = true;
|
||||
std::cout << "page " << pageno << ": expected filter "
|
||||
<< desired_filter
|
||||
std::cout << "page " << pageno << ": expected filter " << desired_filter
|
||||
<< "; actual filter = " << filter.unparse() << std::endl;
|
||||
}
|
||||
if (!color_space.isNameAndEquals(desired_color_space)) {
|
||||
this_errors = errors = true;
|
||||
std::cout << "page " << pageno << ": expected color space "
|
||||
<< desired_color_space
|
||||
<< "; actual color space = " << color_space.unparse()
|
||||
<< std::endl;
|
||||
std::cout << "page " << pageno << ": expected color space " << desired_color_space
|
||||
<< "; actual color space = " << color_space.unparse() << std::endl;
|
||||
}
|
||||
|
||||
if (!this_errors) {
|
||||
@ -293,8 +285,7 @@ check(
|
||||
std::shared_ptr<Buffer> desired_data(b_p.getBuffer());
|
||||
|
||||
if (desired_data->getSize() != actual_data->getSize()) {
|
||||
std::cout << "page " << pageno << ": image data length mismatch"
|
||||
<< std::endl;
|
||||
std::cout << "page " << pageno << ": image data length mismatch" << std::endl;
|
||||
this_errors = errors = true;
|
||||
} else {
|
||||
// Compare bytes. For JPEG, allow a certain number of
|
||||
@ -308,8 +299,7 @@ check(
|
||||
size_t len = actual_data->getSize();
|
||||
unsigned int mismatches = 0;
|
||||
int tolerance = (desired_filter == "/DCTDecode" ? 10 : 0);
|
||||
size_t threshold =
|
||||
(desired_filter == "/DCTDecode" ? len / 40U : 0);
|
||||
size_t threshold = (desired_filter == "/DCTDecode" ? len / 40U : 0);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
int delta = actual_bytes[i] - desired_bytes[i];
|
||||
if ((delta > tolerance) || (delta < -tolerance)) {
|
||||
@ -317,9 +307,8 @@ check(
|
||||
}
|
||||
}
|
||||
if (mismatches > threshold) {
|
||||
std::cout << "page " << pageno << ": "
|
||||
<< desired_color_space << ", " << desired_filter
|
||||
<< ": mismatches: " << mismatches << " of " << len
|
||||
std::cout << "page " << pageno << ": " << desired_color_space << ", "
|
||||
<< desired_filter << ": mismatches: " << mismatches << " of " << len
|
||||
<< std::endl;
|
||||
this_errors = errors = true;
|
||||
}
|
||||
|
@ -132,8 +132,7 @@ SF_XORDecode::setDecodeParms(QPDFObjectHandle decode_parms)
|
||||
this->key = buf->getBuffer()[0];
|
||||
return true;
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << "Error extracting key for /XORDecode: " << e.what()
|
||||
<< std::endl;
|
||||
std::cerr << "Error extracting key for /XORDecode: " << e.what() << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -203,8 +202,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
|
||||
void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override;
|
||||
|
||||
void registerStream(
|
||||
QPDFObjectHandle stream,
|
||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self);
|
||||
QPDFObjectHandle stream, std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self);
|
||||
|
||||
private:
|
||||
bool maybeReplace(
|
||||
@ -300,12 +298,10 @@ StreamReplacer::maybeReplace(
|
||||
// changes. For example, an image resampler might change the
|
||||
// dimensions or other properties of the image.
|
||||
dict_updates->replaceKey(
|
||||
"/OrigLength",
|
||||
QPDFObjectHandle::newInteger(QIntC::to_longlong(out->getSize())));
|
||||
"/OrigLength", QPDFObjectHandle::newInteger(QIntC::to_longlong(out->getSize())));
|
||||
// We are also storing the "key" that we will access when
|
||||
// writing the data.
|
||||
this->keys[og] = QIntC::to_uchar(
|
||||
(og.getObj() * QIntC::to_int(out->getSize())) & 0xff);
|
||||
this->keys[og] = QIntC::to_uchar((og.getObj() * QIntC::to_int(out->getSize())) & 0xff);
|
||||
}
|
||||
|
||||
if (pipeline) {
|
||||
@ -319,8 +315,7 @@ StreamReplacer::maybeReplace(
|
||||
|
||||
void
|
||||
StreamReplacer::registerStream(
|
||||
QPDFObjectHandle stream,
|
||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self)
|
||||
QPDFObjectHandle stream, std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self)
|
||||
{
|
||||
QPDFObjGen og(stream.getObjGen());
|
||||
|
||||
@ -344,8 +339,7 @@ StreamReplacer::registerStream(
|
||||
try {
|
||||
should_replace = maybeReplace(og, stream, nullptr, &dict_updates);
|
||||
} catch (std::exception& e) {
|
||||
stream.warnIfPossible(
|
||||
std::string("exception while attempting to replace: ") + e.what());
|
||||
stream.warnIfPossible(std::string("exception while attempting to replace: ") + e.what());
|
||||
}
|
||||
|
||||
if (should_replace) {
|
||||
@ -369,8 +363,7 @@ StreamReplacer::registerStream(
|
||||
// /XORDecode filter.
|
||||
QPDFObjectHandle decode_parms =
|
||||
QPDFObjectHandle::newDictionary({{"/KeyStream", dp_stream}});
|
||||
stream.replaceStreamData(
|
||||
self, QPDFObjectHandle::newName("/XORDecode"), decode_parms);
|
||||
stream.replaceStreamData(self, QPDFObjectHandle::newName("/XORDecode"), decode_parms);
|
||||
// Further, if /ProtectXOR = true, we disable filtering on write
|
||||
// so that QPDFWriter will not decode the stream even though we
|
||||
// have registered a stream filter for /XORDecode.
|
||||
@ -393,14 +386,12 @@ StreamReplacer::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
|
||||
// Since this only gets called for streams we already
|
||||
// determined we are replacing, a false return would indicate
|
||||
// a logic error.
|
||||
throw std::logic_error(
|
||||
"should_replace return false in provideStreamData");
|
||||
throw std::logic_error("should_replace return false in provideStreamData");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process(
|
||||
char const* infilename, char const* outfilename, bool decode_specialized)
|
||||
process(char const* infilename, char const* outfilename, bool decode_specialized)
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename);
|
||||
@ -434,8 +425,7 @@ static void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "\n"
|
||||
<< "Usage: " << whoami
|
||||
<< " [--decode-specialized] infile outfile\n"
|
||||
<< "Usage: " << whoami << " [--decode-specialized] infile outfile\n"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
@ -468,8 +458,7 @@ main(int argc, char* argv[])
|
||||
// decode our streams. This is not a real filter, so no real
|
||||
// PDF reading application would be able to interpret it. This
|
||||
// is just for illustrative purposes.
|
||||
QPDF::registerStreamFilter(
|
||||
"/XORDecode", [] { return std::make_shared<SF_XORDecode>(); });
|
||||
QPDF::registerStreamFilter("/XORDecode", [] { return std::make_shared<SF_XORDecode>(); });
|
||||
// Do the actual processing.
|
||||
process(infilename, outfilename, decode_specialized);
|
||||
} catch (std::exception& e) {
|
||||
|
@ -13,8 +13,7 @@ static char const* whoami = nullptr;
|
||||
void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
||||
<< std::endl
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]" << std::endl
|
||||
<< "Double size of all pages in infile.pdf;"
|
||||
<< " write output to outfile.pdf" << std::endl;
|
||||
exit(2);
|
||||
@ -33,16 +32,13 @@ doubleBoxSize(QPDFPageObjectHelper& page, char const* box_name)
|
||||
}
|
||||
if (!box.isRectangle()) {
|
||||
throw std::runtime_error(
|
||||
std::string("box ") + box_name +
|
||||
" is not an array of four elements");
|
||||
std::string("box ") + box_name + " is not an array of four elements");
|
||||
}
|
||||
std::vector<QPDFObjectHandle> doubled;
|
||||
for (auto& item: box.aitems()) {
|
||||
doubled.push_back(
|
||||
QPDFObjectHandle::newReal(item.getNumericValue() * 2.0, 2));
|
||||
doubled.push_back(QPDFObjectHandle::newReal(item.getNumericValue() * 2.0, 2));
|
||||
}
|
||||
page.getObjectHandle().replaceKey(
|
||||
box_name, QPDFObjectHandle::newArray(doubled));
|
||||
page.getObjectHandle().replaceKey(box_name, QPDFObjectHandle::newArray(doubled));
|
||||
}
|
||||
|
||||
int
|
||||
@ -93,11 +89,9 @@ main(int argc, char* argv[])
|
||||
w.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
std::cout << whoami << ": new file written to " << outfilename << std::endl;
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
std::cerr << whoami << " processing file " << infilename << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,7 @@ void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile outfile" << std::endl
|
||||
<< "Applies token filters to infile and writes outfile"
|
||||
<< std::endl;
|
||||
<< "Applies token filters to infile and writes outfile" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -82,17 +81,13 @@ class ColorToGray: public QPDFObjectHandle::TokenFilter
|
||||
bool
|
||||
ColorToGray::isNumeric(QPDFTokenizer::token_type_e token_type)
|
||||
{
|
||||
return (
|
||||
(token_type == QPDFTokenizer::tt_integer) ||
|
||||
(token_type == QPDFTokenizer::tt_real));
|
||||
return ((token_type == QPDFTokenizer::tt_integer) || (token_type == QPDFTokenizer::tt_real));
|
||||
}
|
||||
|
||||
bool
|
||||
ColorToGray::isIgnorable(QPDFTokenizer::token_type_e token_type)
|
||||
{
|
||||
return (
|
||||
(token_type == QPDFTokenizer::tt_space) ||
|
||||
(token_type == QPDFTokenizer::tt_comment));
|
||||
return ((token_type == QPDFTokenizer::tt_space) || (token_type == QPDFTokenizer::tt_comment));
|
||||
}
|
||||
|
||||
double
|
||||
@ -128,8 +123,7 @@ ColorToGray::handleToken(QPDFTokenizer::Token const& token)
|
||||
// kinds of operands, replace the command. Flush any additional
|
||||
// accumulated tokens to keep the stack only four tokens deep.
|
||||
|
||||
while ((!this->all_stack.empty()) &&
|
||||
isIgnorable(this->all_stack.at(0).getType())) {
|
||||
while ((!this->all_stack.empty()) && isIgnorable(this->all_stack.at(0).getType())) {
|
||||
writeToken(this->all_stack.at(0));
|
||||
this->all_stack.pop_front();
|
||||
}
|
||||
@ -138,8 +132,7 @@ ColorToGray::handleToken(QPDFTokenizer::Token const& token)
|
||||
if (!isIgnorable(token_type)) {
|
||||
this->stack.push_back(token);
|
||||
if ((this->stack.size() == 4) && token.isWord("rg") &&
|
||||
(isNumeric(this->stack.at(0).getType())) &&
|
||||
(isNumeric(this->stack.at(1).getType())) &&
|
||||
(isNumeric(this->stack.at(0).getType())) && (isNumeric(this->stack.at(1).getType())) &&
|
||||
(isNumeric(this->stack.at(2).getType()))) {
|
||||
double r = numericValue(this->stack.at(0));
|
||||
double g = numericValue(this->stack.at(1));
|
||||
@ -195,11 +188,9 @@ main(int argc, char* argv[])
|
||||
// applied. See comments on the filters for additional
|
||||
// details.
|
||||
page.addContentTokenFilter(
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter>(
|
||||
new StringReverser));
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter>(new StringReverser));
|
||||
page.addContentTokenFilter(
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter>(
|
||||
new ColorToGray));
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter>(new ColorToGray));
|
||||
}
|
||||
|
||||
QPDFWriter w(pdf, outfilename);
|
||||
|
@ -14,8 +14,7 @@ static char const* whoami = nullptr;
|
||||
void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
||||
<< std::endl
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]" << std::endl
|
||||
<< "Invert some images in infile.pdf;"
|
||||
<< " write output to outfile.pdf" << std::endl;
|
||||
exit(2);
|
||||
@ -37,8 +36,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
|
||||
void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override;
|
||||
|
||||
void registerImage(
|
||||
QPDFObjectHandle image,
|
||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self);
|
||||
QPDFObjectHandle image, std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self);
|
||||
|
||||
private:
|
||||
std::map<QPDFObjGen, QPDFObjectHandle> copied_images;
|
||||
@ -46,8 +44,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
|
||||
|
||||
void
|
||||
ImageInverter::registerImage(
|
||||
QPDFObjectHandle image,
|
||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self)
|
||||
QPDFObjectHandle image, std::shared_ptr<QPDFObjectHandle::StreamDataProvider> self)
|
||||
{
|
||||
// replaceStreamData requires a pointer holder to the stream data
|
||||
// provider, but there's no way for us to generate one ourselves,
|
||||
@ -76,8 +73,7 @@ ImageInverter::registerImage(
|
||||
// filterable in the input QPDF object, so we don't have to deal
|
||||
// with it explicitly here. We could explicitly use /DCTDecode and
|
||||
// write through a DCT filter if we wanted.
|
||||
image.replaceStreamData(
|
||||
self, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
image.replaceStreamData(self, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
}
|
||||
|
||||
void
|
||||
@ -86,8 +82,7 @@ ImageInverter::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
|
||||
// Use the object and generation number supplied to look up the
|
||||
// image data. Then invert the image data and write the inverted
|
||||
// data to the pipeline.
|
||||
std::shared_ptr<Buffer> data =
|
||||
this->copied_images[og].getStreamData(qpdf_dl_all);
|
||||
std::shared_ptr<Buffer> data = this->copied_images[og].getStreamData(qpdf_dl_all);
|
||||
size_t size = data->getSize();
|
||||
unsigned char* buf = data->getBuffer();
|
||||
unsigned char ch;
|
||||
@ -133,18 +128,15 @@ main(int argc, char* argv[])
|
||||
QPDFObjectHandle& image = iter.second;
|
||||
QPDFObjectHandle image_dict = image.getDict();
|
||||
QPDFObjectHandle color_space = image_dict.getKey("/ColorSpace");
|
||||
QPDFObjectHandle bits_per_component =
|
||||
image_dict.getKey("/BitsPerComponent");
|
||||
QPDFObjectHandle bits_per_component = image_dict.getKey("/BitsPerComponent");
|
||||
|
||||
// For our example, we can only work with images 8-bit
|
||||
// grayscale images that we can fully decode. Use
|
||||
// pipeStreamData with a null pipeline to determine
|
||||
// whether the image is filterable. Directly inspect
|
||||
// keys to determine the image type.
|
||||
if (image.pipeStreamData(
|
||||
nullptr, qpdf_ef_compress, qpdf_dl_all) &&
|
||||
color_space.isNameAndEquals("/DeviceGray") &&
|
||||
bits_per_component.isInteger() &&
|
||||
if (image.pipeStreamData(nullptr, qpdf_ef_compress, qpdf_dl_all) &&
|
||||
color_space.isNameAndEquals("/DeviceGray") && bits_per_component.isInteger() &&
|
||||
(bits_per_component.getIntValue() == 8)) {
|
||||
inv->registerImage(image, p);
|
||||
}
|
||||
@ -159,11 +151,9 @@ main(int argc, char* argv[])
|
||||
w.setStaticID(true); // for testing only
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
std::cout << whoami << ": new file written to " << outfilename << std::endl;
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
std::cerr << whoami << " processing file " << infilename << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
@ -61,15 +61,11 @@ main(int argc, char* argv[])
|
||||
}
|
||||
while (qpdf_more_warnings(qpdf)) {
|
||||
warnings = 1;
|
||||
printf(
|
||||
"warning: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
printf("warning: %s\n", qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
}
|
||||
if (qpdf_has_error(qpdf)) {
|
||||
errors = 1;
|
||||
printf(
|
||||
"error: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
printf("error: %s\n", qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
}
|
||||
qpdf_cleanup(&qpdf);
|
||||
if (errors) {
|
||||
|
@ -16,8 +16,7 @@ static char const* whoami = nullptr;
|
||||
void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami
|
||||
<< " --in in_file [--out out_file] [--key key [--val val]?]+\n"
|
||||
std::cerr << "Usage: " << whoami << " --in in_file [--out out_file] [--key key [--val val]?]+\n"
|
||||
<< "Modifies/Adds/Removes PDF /Info entries in the in_file\n"
|
||||
<< "and stores the result in out_file\n"
|
||||
<< "Special mode: " << whoami << " --dump file\n"
|
||||
@ -26,8 +25,7 @@ usage()
|
||||
}
|
||||
|
||||
void
|
||||
dumpInfoDict(
|
||||
QPDF& pdf, std::ostream& os = std::cout, std::string const& sep = ":\t")
|
||||
dumpInfoDict(QPDF& pdf, std::ostream& os = std::cout, std::string const& sep = ":\t")
|
||||
{
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
if (trailer.hasKey("/Info")) {
|
||||
@ -164,8 +162,7 @@ main(int argc, char* argv[])
|
||||
try {
|
||||
(void)remove(fl_out);
|
||||
QUtil::os_wrapper(
|
||||
"rename " + fl_tmp + " " + std::string(fl_out),
|
||||
rename(fl_tmp.c_str(), fl_out));
|
||||
"rename " + fl_tmp + " " + std::string(fl_out), rename(fl_tmp.c_str(), fl_out));
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
|
@ -11,8 +11,7 @@ void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " outfile.pdf" << std::endl
|
||||
<< "Create some name/number trees and write to a file"
|
||||
<< std::endl;
|
||||
<< "Create some name/number trees and write to a file" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -61,24 +60,19 @@ main(int argc, char* argv[])
|
||||
name_tree.insert("R", QPDFObjectHandle::newUnicodeString("rook"));
|
||||
name_tree.insert("B", QPDFObjectHandle::newUnicodeString("bishop"));
|
||||
name_tree.insert("N", QPDFObjectHandle::newUnicodeString("knight"));
|
||||
auto iter =
|
||||
name_tree.insert("P", QPDFObjectHandle::newUnicodeString("pawn"));
|
||||
auto iter = name_tree.insert("P", QPDFObjectHandle::newUnicodeString("pawn"));
|
||||
// Look at the iterator
|
||||
std::cout << "just inserted " << iter->first << " -> "
|
||||
<< iter->second.unparse() << std::endl;
|
||||
std::cout << "just inserted " << iter->first << " -> " << iter->second.unparse() << std::endl;
|
||||
--iter;
|
||||
std::cout << "predecessor: " << iter->first << " -> "
|
||||
<< iter->second.unparse() << std::endl;
|
||||
std::cout << "predecessor: " << iter->first << " -> " << iter->second.unparse() << std::endl;
|
||||
++iter;
|
||||
++iter;
|
||||
std::cout << "successor: " << iter->first << " -> "
|
||||
<< iter->second.unparse() << std::endl;
|
||||
std::cout << "successor: " << iter->first << " -> " << iter->second.unparse() << std::endl;
|
||||
|
||||
// Use range-for iteration
|
||||
std::cout << "Name tree items:" << std::endl;
|
||||
for (auto i: name_tree) {
|
||||
std::cout << " " << i.first << " -> " << i.second.unparse()
|
||||
<< std::endl;
|
||||
std::cout << " " << i.first << " -> " << i.second.unparse() << std::endl;
|
||||
}
|
||||
|
||||
// This is a small tree, so everything will be at the root. We can
|
||||
@ -107,14 +101,13 @@ main(int argc, char* argv[])
|
||||
|
||||
// 10.2 API
|
||||
iter = name_tree.find("Q");
|
||||
std::cout << "Q: " << iter->first << " -> " << iter->second.unparse()
|
||||
<< std::endl;
|
||||
std::cout << "Q: " << iter->first << " -> " << iter->second.unparse() << std::endl;
|
||||
iter = name_tree.find("W");
|
||||
std::cout << "W found: " << (iter != name_tree.end()) << std::endl;
|
||||
// Allow find to return predecessor
|
||||
iter = name_tree.find("W", true);
|
||||
std::cout << "W's predecessor: " << iter->first << " -> "
|
||||
<< iter->second.unparse() << std::endl;
|
||||
std::cout << "W's predecessor: " << iter->first << " -> " << iter->second.unparse()
|
||||
<< std::endl;
|
||||
|
||||
// We can also remove items
|
||||
std::cout << "Remove P: " << name_tree.remove("P", &obj) << std::endl;
|
||||
@ -124,8 +117,8 @@ main(int argc, char* argv[])
|
||||
iter = name_tree.find("K");
|
||||
std::cout << "Find K: " << iter->second.unparse() << std::endl;
|
||||
iter.remove();
|
||||
std::cout << "Iter after removing K: " << iter->first << " -> "
|
||||
<< iter->second.unparse() << std::endl;
|
||||
std::cout << "Iter after removing K: " << iter->first << " -> " << iter->second.unparse()
|
||||
<< std::endl;
|
||||
std::cout << "Has K?: " << name_tree.hasName("K") << std::endl;
|
||||
|
||||
// Illustrate some more advanced usage using number trees. These
|
||||
@ -142,8 +135,7 @@ main(int argc, char* argv[])
|
||||
example.replaceKey("/NumberTree", number_tree_oh);
|
||||
auto iter2 = number_tree.begin();
|
||||
for (int i = 7; i <= 350; i += 7) {
|
||||
iter2.insertAfter(
|
||||
i, QPDFObjectHandle::newString("-" + std::to_string(i) + "-"));
|
||||
iter2.insertAfter(i, QPDFObjectHandle::newString("-" + std::to_string(i) + "-"));
|
||||
}
|
||||
std::cout << "Numbers:" << std::endl;
|
||||
int n = 1;
|
||||
|
@ -31,8 +31,7 @@ stamp_page(char const* infile, char const* stampfile, char const* outfile)
|
||||
stamppdf.processFile(stampfile);
|
||||
|
||||
// Get first page from other file
|
||||
QPDFPageObjectHelper stamp_page_1 =
|
||||
QPDFPageDocumentHelper(stamppdf).getAllPages().at(0);
|
||||
QPDFPageObjectHelper stamp_page_1 = QPDFPageDocumentHelper(stamppdf).getAllPages().at(0);
|
||||
// Convert page to a form XObject
|
||||
QPDFObjectHandle foreign_fo = stamp_page_1.getFormXObjectForPage();
|
||||
// Copy form XObject to the input file
|
||||
@ -48,8 +47,8 @@ stamp_page(char const* infile, char const* stampfile, char const* outfile)
|
||||
// Generate content to place the form XObject centered within
|
||||
// destination page's trim box.
|
||||
QPDFMatrix m;
|
||||
std::string content = ph.placeFormXObject(
|
||||
stamp_fo, name, ph.getTrimBox().getArrayAsRectangle(), m);
|
||||
std::string content =
|
||||
ph.placeFormXObject(stamp_fo, name, ph.getTrimBox().getArrayAsRectangle(), m);
|
||||
if (!content.empty()) {
|
||||
// Append the content to the page's content. Surround the
|
||||
// original content with q...Q to the new content from the
|
||||
|
@ -35,11 +35,9 @@ ParserCallbacks::contentSize(size_t size)
|
||||
}
|
||||
|
||||
void
|
||||
ParserCallbacks::handleObject(
|
||||
QPDFObjectHandle obj, size_t offset, size_t length)
|
||||
ParserCallbacks::handleObject(QPDFObjectHandle obj, size_t offset, size_t length)
|
||||
{
|
||||
std::cout << obj.getTypeName() << ", offset=" << offset
|
||||
<< ", length=" << length << ": ";
|
||||
std::cout << obj.getTypeName() << ", offset=" << offset << ", length=" << length << ": ";
|
||||
if (obj.isInlineImage()) {
|
||||
std::cout << QUtil::hex_encode(obj.getInlineImageValue()) << std::endl;
|
||||
} else {
|
||||
@ -67,8 +65,7 @@ main(int argc, char* argv[])
|
||||
try {
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
std::vector<QPDFPageObjectHelper> pages = QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
if ((pageno < 1) || (QIntC::to_size(pageno) > pages.size())) {
|
||||
usage();
|
||||
}
|
||||
|
@ -11,10 +11,8 @@ static char const* whoami = nullptr;
|
||||
void
|
||||
usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf value"
|
||||
<< std::endl
|
||||
<< "Set the value of all text fields to a specified value"
|
||||
<< std::endl;
|
||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf value" << std::endl
|
||||
<< "Set the value of all text fields to a specified value" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -55,8 +53,7 @@ main(int argc, char* argv[])
|
||||
for (auto& annot: afdh.getWidgetAnnotationsForPage(page)) {
|
||||
// For each annotation, find its associated field. If
|
||||
// it's a text field, set its value.
|
||||
QPDFFormFieldObjectHelper ffh =
|
||||
afdh.getFieldForAnnotation(annot);
|
||||
QPDFFormFieldObjectHelper ffh = afdh.getFieldForAnnotation(annot);
|
||||
if (ffh.getFieldType() == "/Tx") {
|
||||
// Set the value. Passing false as the second
|
||||
// value prevents qpdf from setting
|
||||
@ -79,8 +76,7 @@ main(int argc, char* argv[])
|
||||
w.setStaticID(true); // for testing only
|
||||
w.write();
|
||||
} catch (std::exception& e) {
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
std::cerr << whoami << " processing file " << infilename << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
@ -22,13 +22,11 @@ process(char const* whoami, char const* infile, std::string outprefix)
|
||||
{
|
||||
QPDF inpdf;
|
||||
inpdf.processFile(infile);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(inpdf).getAllPages();
|
||||
std::vector<QPDFPageObjectHelper> pages = QPDFPageDocumentHelper(inpdf).getAllPages();
|
||||
int pageno_len = QIntC::to_int(std::to_string(pages.size()).length());
|
||||
int pageno = 0;
|
||||
for (auto& page: pages) {
|
||||
std::string outfile =
|
||||
outprefix + QUtil::int_to_string(++pageno, pageno_len) + ".pdf";
|
||||
std::string outfile = outprefix + QUtil::int_to_string(++pageno, pageno_len) + ".pdf";
|
||||
QPDF outpdf;
|
||||
outpdf.emptyPDF();
|
||||
QPDFPageDocumentHelper(outpdf).addPage(page, false);
|
||||
|
@ -83,8 +83,7 @@ main(int argc, char* argv[])
|
||||
* saved data. You can use other qpdf logger functions to capture
|
||||
* informational output, warnings, and errors.
|
||||
*/
|
||||
qpdflogger_set_save(
|
||||
l, qpdf_log_dest_custom, save_to_file, (void*)outfile, 0);
|
||||
qpdflogger_set_save(l, qpdf_log_dest_custom, save_to_file, (void*)outfile, 0);
|
||||
qpdflogger_cleanup(&l);
|
||||
j = qpdfjob_init();
|
||||
status = (qpdfjob_initialize_from_argv(j, j_argv) || qpdfjob_run(j));
|
||||
|
@ -20,15 +20,10 @@ usageExit(std::string const& msg)
|
||||
<< whoami << ": " << msg << std::endl
|
||||
<< std::endl
|
||||
<< "For help:" << std::endl
|
||||
<< " " << whoami << " --help=usage usage information"
|
||||
<< std::endl
|
||||
<< " " << whoami << " --help=topic help on a topic"
|
||||
<< std::endl
|
||||
<< " " << whoami << " --help=--option help on an option"
|
||||
<< std::endl
|
||||
<< " " << whoami
|
||||
<< " --help general help and a topic list"
|
||||
<< std::endl
|
||||
<< " " << whoami << " --help=usage usage information" << std::endl
|
||||
<< " " << whoami << " --help=topic help on a topic" << std::endl
|
||||
<< " " << whoami << " --help=--option help on an option" << std::endl
|
||||
<< " " << whoami << " --help general help and a topic list" << std::endl
|
||||
<< std::endl;
|
||||
exit(QPDFJob::EXIT_ERROR);
|
||||
}
|
||||
|
@ -14,8 +14,7 @@ main(int argc, char* argv[])
|
||||
auto whoami = QUtil::getWhoami(argv[0]);
|
||||
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << whoami << " file attachment-key outfile"
|
||||
<< std::endl;
|
||||
std::cerr << "Usage: " << whoami << " file attachment-key outfile" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,8 @@ FuzzHelper::FuzzHelper(unsigned char const* data, size_t size) :
|
||||
std::shared_ptr<QPDF>
|
||||
FuzzHelper::getQpdf()
|
||||
{
|
||||
auto is = std::shared_ptr<InputSource>(
|
||||
new BufferInputSource("fuzz input", &this->input_buffer));
|
||||
auto is =
|
||||
std::shared_ptr<InputSource>(new BufferInputSource("fuzz input", &this->input_buffer));
|
||||
auto qpdf = QPDF::create();
|
||||
qpdf->processInputSource(is);
|
||||
return qpdf;
|
||||
@ -99,8 +99,7 @@ FuzzHelper::testWrite()
|
||||
w = getWriter(q);
|
||||
w->setStaticID(true);
|
||||
w->setLinearization(true);
|
||||
w->setR6EncryptionParameters(
|
||||
"u", "o", true, true, true, true, true, true, qpdf_r3p_full, true);
|
||||
w->setR6EncryptionParameters("u", "o", true, true, true, true, true, true, qpdf_r3p_full, true);
|
||||
doWrite(w);
|
||||
|
||||
q = getQpdf();
|
||||
|
@ -11,8 +11,7 @@ main(int argc, char** argv)
|
||||
std::shared_ptr<char> file_buf;
|
||||
size_t size = 0;
|
||||
QUtil::read_file_into_memory(argv[i], file_buf, size);
|
||||
LLVMFuzzerTestOneInput(
|
||||
reinterpret_cast<unsigned char*>(file_buf.get()), size);
|
||||
LLVMFuzzerTestOneInput(reinterpret_cast<unsigned char*>(file_buf.get()), size);
|
||||
std::cout << argv[i] << " successful" << std::endl;
|
||||
}
|
||||
return 0;
|
||||
|
@ -26,8 +26,7 @@ void
|
||||
FuzzHelper::doChecks()
|
||||
{
|
||||
Pl_Discard discard;
|
||||
Pl_TIFFPredictor p(
|
||||
"decoder", &discard, Pl_TIFFPredictor::a_decode, 16, 1, 8);
|
||||
Pl_TIFFPredictor p("decoder", &discard, Pl_TIFFPredictor::a_decode, 16, 1, 8);
|
||||
p.write(const_cast<unsigned char*>(data), size);
|
||||
p.finish();
|
||||
}
|
||||
|
@ -31,11 +31,9 @@ class QPDF_DLL_CLASS BufferInputSource: public InputSource
|
||||
// If own_memory is true, BufferInputSource will delete the buffer
|
||||
// when finished with it. Otherwise, the caller owns the memory.
|
||||
QPDF_DLL
|
||||
BufferInputSource(
|
||||
std::string const& description, Buffer* buf, bool own_memory = false);
|
||||
BufferInputSource(std::string const& description, Buffer* buf, bool own_memory = false);
|
||||
QPDF_DLL
|
||||
BufferInputSource(
|
||||
std::string const& description, std::string const& contents);
|
||||
BufferInputSource(std::string const& description, std::string const& contents);
|
||||
QPDF_DLL
|
||||
virtual ~BufferInputSource();
|
||||
QPDF_DLL
|
||||
|
@ -230,9 +230,6 @@ enum pdf_annotation_flag_e {
|
||||
};
|
||||
|
||||
/* Encryption/password status for QPDFJob */
|
||||
enum qpdf_encryption_status_e {
|
||||
qpdf_es_encrypted = 1 << 0,
|
||||
qpdf_es_password_incorrect = 1 << 1
|
||||
};
|
||||
enum qpdf_encryption_status_e { qpdf_es_encrypted = 1 << 0, qpdf_es_password_incorrect = 1 << 1 };
|
||||
|
||||
#endif /* QPDFCONSTANTS_H */
|
||||
|
@ -69,17 +69,9 @@ class QPDF_DLL_CLASS InputSource
|
||||
// methods return true and leave the input source positioned
|
||||
// wherever check() left it at the end of the matching pattern.
|
||||
QPDF_DLL
|
||||
bool findFirst(
|
||||
char const* start_chars,
|
||||
qpdf_offset_t offset,
|
||||
size_t len,
|
||||
Finder& finder);
|
||||
bool findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder);
|
||||
QPDF_DLL
|
||||
bool findLast(
|
||||
char const* start_chars,
|
||||
qpdf_offset_t offset,
|
||||
size_t len,
|
||||
Finder& finder);
|
||||
bool findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder);
|
||||
|
||||
virtual qpdf_offset_t findAndSkipNextEOL() = 0;
|
||||
virtual std::string const& getName() const = 0;
|
||||
@ -144,8 +136,7 @@ InputSource::fastTell()
|
||||
loadBuffer();
|
||||
} else {
|
||||
auto curr = tell();
|
||||
if (curr < this->buf_start ||
|
||||
curr >= (this->buf_start + this->buf_len)) {
|
||||
if (curr < this->buf_start || curr >= (this->buf_start + this->buf_len)) {
|
||||
loadBuffer();
|
||||
} else {
|
||||
this->last_offset = curr;
|
||||
|
@ -104,19 +104,14 @@ class JSON
|
||||
// the first item and always set it to false.
|
||||
QPDF_DLL
|
||||
static void writeDictionaryItem(
|
||||
Pipeline*,
|
||||
bool& first,
|
||||
std::string const& key,
|
||||
JSON const& value,
|
||||
size_t depth = 0);
|
||||
Pipeline*, bool& first, std::string const& key, JSON const& value, size_t depth = 0);
|
||||
// Write just the key of a new dictionary item, useful if writing
|
||||
// nested structures. Calls writeNext.
|
||||
QPDF_DLL
|
||||
static void writeDictionaryKey(
|
||||
Pipeline* p, bool& first, std::string const& key, size_t depth = 0);
|
||||
static void
|
||||
writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth = 0);
|
||||
QPDF_DLL
|
||||
static void writeArrayItem(
|
||||
Pipeline*, bool& first, JSON const& element, size_t depth = 0);
|
||||
static void writeArrayItem(Pipeline*, bool& first, JSON const& element, size_t depth = 0);
|
||||
// If writing nested structures incrementally, call writeNext
|
||||
// before opening a new array or container in the midst of an
|
||||
// existing one. The `first` you pass to writeNext should be the
|
||||
@ -188,8 +183,7 @@ class JSON
|
||||
QPDF_DLL
|
||||
bool isNull() const;
|
||||
QPDF_DLL
|
||||
bool forEachDictItem(
|
||||
std::function<void(std::string const& key, JSON value)> fn) const;
|
||||
bool forEachDictItem(std::function<void(std::string const& key, JSON value)> fn) const;
|
||||
QPDF_DLL
|
||||
bool forEachArrayItem(std::function<void(JSON value)> fn) const;
|
||||
|
||||
@ -239,8 +233,7 @@ class JSON
|
||||
f_optional = 1 << 0,
|
||||
};
|
||||
QPDF_DLL
|
||||
bool checkSchema(
|
||||
JSON schema, unsigned long flags, std::list<std::string>& errors);
|
||||
bool checkSchema(JSON schema, unsigned long flags, std::list<std::string>& errors);
|
||||
|
||||
// Same as passing 0 for flags
|
||||
QPDF_DLL
|
||||
@ -311,8 +304,7 @@ class JSON
|
||||
// methods and decrementing on end methods.
|
||||
|
||||
QPDF_DLL
|
||||
virtual bool
|
||||
dictionaryItem(std::string const& key, JSON const& value) = 0;
|
||||
virtual bool dictionaryItem(std::string const& key, JSON const& value) = 0;
|
||||
QPDF_DLL
|
||||
virtual bool arrayItem(JSON const& value) = 0;
|
||||
};
|
||||
@ -339,8 +331,7 @@ class JSON
|
||||
|
||||
private:
|
||||
static std::string encode_string(std::string const& utf8);
|
||||
static void
|
||||
writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter);
|
||||
static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter);
|
||||
|
||||
enum value_type_e {
|
||||
vt_none,
|
||||
|
@ -54,15 +54,10 @@ class QPDF_DLL_CLASS Pl_Function: public Pipeline
|
||||
// is thrown.
|
||||
typedef int (*writer_c_t)(unsigned char const*, size_t, void*);
|
||||
QPDF_DLL
|
||||
Pl_Function(
|
||||
char const* identifier, Pipeline* next, writer_c_t fn, void* udata);
|
||||
Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata);
|
||||
typedef int (*writer_c_char_t)(char const*, size_t, void*);
|
||||
QPDF_DLL
|
||||
Pl_Function(
|
||||
char const* identifier,
|
||||
Pipeline* next,
|
||||
writer_c_char_t fn,
|
||||
void* udata);
|
||||
Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata);
|
||||
|
||||
QPDF_DLL
|
||||
virtual ~Pl_Function();
|
||||
|
@ -49,9 +49,7 @@ class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline
|
||||
// provided, any output written by the filter will be discarded.
|
||||
QPDF_DLL
|
||||
Pl_QPDFTokenizer(
|
||||
char const* identifier,
|
||||
QPDFObjectHandle::TokenFilter* filter,
|
||||
Pipeline* next = nullptr);
|
||||
char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
QPDF_DLL
|
||||
virtual ~Pl_QPDFTokenizer();
|
||||
QPDF_DLL
|
||||
|
@ -78,9 +78,8 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a "
|
||||
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
|
||||
<< "-byte unsigned type";
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
@ -93,8 +92,7 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
convert(From const& i)
|
||||
{
|
||||
// From and To are both signed.
|
||||
if ((i < std::numeric_limits<To>::min()) ||
|
||||
(i > std::numeric_limits<To>::max())) {
|
||||
if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) {
|
||||
error(i);
|
||||
}
|
||||
return static_cast<To>(i);
|
||||
@ -105,9 +103,8 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a "
|
||||
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
|
||||
<< "-byte signed type";
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte signed type to a " << sizeof(To) << "-byte signed type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
@ -134,9 +131,8 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a "
|
||||
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
|
||||
<< "-byte unsigned type";
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte signed type to a " << sizeof(To) << "-byte unsigned type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
@ -150,8 +146,7 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
{
|
||||
// From is unsigned, and to is signed. Convert To's max to the
|
||||
// unsigned version of To and compare i against that.
|
||||
auto maxval = static_cast<typename to_u<To>::type>(
|
||||
std::numeric_limits<To>::max());
|
||||
auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max());
|
||||
if (i > maxval) {
|
||||
error(i);
|
||||
}
|
||||
@ -163,9 +158,8 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a "
|
||||
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
|
||||
<< "-byte signed type";
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte unsigned type to a " << sizeof(To) << "-byte signed type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
@ -263,15 +257,12 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
if ((delta > 0) && ((std::numeric_limits<T>::max() - cur) < delta)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "adding " << delta << " to " << cur
|
||||
<< " would cause an integer overflow";
|
||||
msg << "adding " << delta << " to " << cur << " would cause an integer overflow";
|
||||
throw std::range_error(msg.str());
|
||||
} else if (
|
||||
(delta < 0) && ((std::numeric_limits<T>::min() - cur) > delta)) {
|
||||
} else if ((delta < 0) && ((std::numeric_limits<T>::min() - cur) > delta)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "adding " << delta << " to " << cur
|
||||
<< " would cause an integer underflow";
|
||||
msg << "adding " << delta << " to " << cur << " would cause an integer underflow";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
}
|
||||
@ -296,12 +287,10 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
msg << "subtracting " << delta << " from " << cur
|
||||
<< " would cause an integer underflow";
|
||||
throw std::range_error(msg.str());
|
||||
} else if (
|
||||
(delta < 0) && ((std::numeric_limits<T>::max() + delta) < cur)) {
|
||||
} else if ((delta < 0) && ((std::numeric_limits<T>::max() + delta) < cur)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "subtracting " << delta << " from " << cur
|
||||
<< " would cause an integer overflow";
|
||||
msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
}
|
||||
|
@ -93,10 +93,7 @@ class QPDF
|
||||
// responsible for closing the file.
|
||||
QPDF_DLL
|
||||
void processFile(
|
||||
char const* description,
|
||||
FILE* file,
|
||||
bool close_file,
|
||||
char const* password = nullptr);
|
||||
char const* description, FILE* file, bool close_file, char const* password = nullptr);
|
||||
|
||||
// Parse a PDF file loaded into a memory buffer. This works
|
||||
// exactly like processFile except that the PDF file is in memory
|
||||
@ -104,17 +101,13 @@ class QPDF
|
||||
// error message in place of the file name.
|
||||
QPDF_DLL
|
||||
void processMemoryFile(
|
||||
char const* description,
|
||||
char const* buf,
|
||||
size_t length,
|
||||
char const* password = nullptr);
|
||||
char const* description, char const* buf, size_t length, char const* password = nullptr);
|
||||
|
||||
// Parse a PDF file loaded from a custom InputSource. If you have
|
||||
// your own method of retrieving a PDF file, you can subclass
|
||||
// InputSource and use this method.
|
||||
QPDF_DLL
|
||||
void processInputSource(
|
||||
std::shared_ptr<InputSource>, char const* password = nullptr);
|
||||
void processInputSource(std::shared_ptr<InputSource>, char const* password = nullptr);
|
||||
|
||||
// Create a PDF from an input source that contains JSON as written
|
||||
// by writeJSON (or qpdf --json-output, version 2 or higher). The
|
||||
@ -234,8 +227,7 @@ class QPDF
|
||||
// QPDFStreamFilter classes.
|
||||
QPDF_DLL
|
||||
static void registerStreamFilter(
|
||||
std::string const& filter_name,
|
||||
std::function<std::shared_ptr<QPDFStreamFilter>()> factory);
|
||||
std::string const& filter_name, std::function<std::shared_ptr<QPDFStreamFilter>()> factory);
|
||||
|
||||
// Parameter settings
|
||||
|
||||
@ -260,8 +252,7 @@ class QPDF
|
||||
// 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
|
||||
[[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
|
||||
@ -481,8 +472,7 @@ class QPDF
|
||||
// reserved object. After this call, reserved will be a reference
|
||||
// to replacement.
|
||||
QPDF_DLL
|
||||
void
|
||||
replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement);
|
||||
void replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement);
|
||||
|
||||
// Copy an object from another QPDF to this one. Starting with
|
||||
// qpdf version 8.3.0, it is no longer necessary to keep the
|
||||
@ -657,8 +647,8 @@ class QPDF
|
||||
int encryption_V,
|
||||
int encryption_R);
|
||||
QPDF_DLL
|
||||
static std::string compute_encryption_key(
|
||||
std::string const& password, EncryptionData const& data);
|
||||
static std::string
|
||||
compute_encryption_key(std::string const& password, EncryptionData const& data);
|
||||
|
||||
QPDF_DLL
|
||||
static void compute_encryption_O_U(
|
||||
@ -843,8 +833,7 @@ class QPDF
|
||||
QPDF_DLL
|
||||
void addPage(QPDFObjectHandle newpage, bool first);
|
||||
QPDF_DLL
|
||||
void
|
||||
addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage);
|
||||
void addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage);
|
||||
QPDF_DLL
|
||||
void removePage(QPDFObjectHandle page);
|
||||
// End legacy page helpers
|
||||
@ -866,8 +855,7 @@ class QPDF
|
||||
std::vector<QPDFObjectHandle>& part8,
|
||||
std::vector<QPDFObjectHandle>& part9)
|
||||
{
|
||||
qpdf.getLinearizedParts(
|
||||
object_stream_data, part4, part6, part7, part8, part9);
|
||||
qpdf.getLinearizedParts(object_stream_data, part4, part6, part7, part8, part9);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -880,8 +868,7 @@ class QPDF
|
||||
int& S,
|
||||
int& O)
|
||||
{
|
||||
return qpdf.generateHintStream(
|
||||
xref, lengths, obj_renumber, hint_stream, S, O);
|
||||
return qpdf.generateHintStream(xref, lengths, obj_renumber, hint_stream, S, O);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -919,10 +906,7 @@ class QPDF
|
||||
|
||||
private:
|
||||
static void
|
||||
copyStreamData(
|
||||
QPDF* qpdf,
|
||||
QPDFObjectHandle const& dest,
|
||||
QPDFObjectHandle const& src)
|
||||
copyStreamData(QPDF* qpdf, QPDFObjectHandle const& dest, QPDFObjectHandle const& src)
|
||||
{
|
||||
qpdf->copyStreamData(dest, src);
|
||||
}
|
||||
@ -968,13 +952,7 @@ class QPDF
|
||||
bool will_retry)
|
||||
{
|
||||
return qpdf->pipeStreamData(
|
||||
og,
|
||||
offset,
|
||||
length,
|
||||
dict,
|
||||
pipeline,
|
||||
suppress_warnings,
|
||||
will_retry);
|
||||
og, offset, length, dict, pipeline, suppress_warnings, will_retry);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1096,16 +1074,13 @@ class QPDF
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry) override;
|
||||
void registerForeignStream(
|
||||
QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
|
||||
void registerForeignStream(
|
||||
QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData>);
|
||||
void registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
|
||||
void registerForeignStream(QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData>);
|
||||
|
||||
private:
|
||||
QPDF& destination_qpdf;
|
||||
std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
|
||||
std::map<QPDFObjGen, std::shared_ptr<ForeignStreamData>>
|
||||
foreign_stream_data;
|
||||
std::map<QPDFObjGen, std::shared_ptr<ForeignStreamData>> foreign_stream_data;
|
||||
};
|
||||
|
||||
class StringDecrypter: public QPDFObjectHandle::StringDecrypter
|
||||
@ -1148,29 +1123,21 @@ class QPDF
|
||||
void read_xref(qpdf_offset_t offset);
|
||||
bool resolveXRefTable();
|
||||
void reconstruct_xref(QPDFExc& e);
|
||||
bool
|
||||
parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes);
|
||||
bool parse_xrefEntry(
|
||||
std::string const& line, qpdf_offset_t& f1, int& f2, char& type);
|
||||
bool parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes);
|
||||
bool parse_xrefEntry(std::string const& line, qpdf_offset_t& f1, int& f2, char& type);
|
||||
qpdf_offset_t read_xrefTable(qpdf_offset_t offset);
|
||||
qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
|
||||
qpdf_offset_t
|
||||
processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
|
||||
void insertXrefEntry(
|
||||
int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
|
||||
void setLastObjectDescription(
|
||||
std::string const& description, QPDFObjGen const& og);
|
||||
qpdf_offset_t processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
|
||||
void insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
|
||||
void setLastObjectDescription(std::string const& description, QPDFObjGen const& og);
|
||||
QPDFObjectHandle readObject(
|
||||
std::shared_ptr<InputSource>,
|
||||
std::string const& description,
|
||||
QPDFObjGen const& og,
|
||||
bool in_object_stream);
|
||||
size_t recoverStreamLength(
|
||||
std::shared_ptr<InputSource> input,
|
||||
QPDFObjGen const& og,
|
||||
qpdf_offset_t stream_offset);
|
||||
QPDFTokenizer::Token
|
||||
readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
|
||||
std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset);
|
||||
QPDFTokenizer::Token readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
|
||||
|
||||
QPDFObjectHandle readObjectAtOffset(
|
||||
bool attempt_recovery,
|
||||
@ -1185,10 +1152,8 @@ class QPDF
|
||||
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
|
||||
QPDFObjectHandle reserveStream(QPDFObjGen const& og);
|
||||
QPDFObjGen nextObjGen();
|
||||
QPDFObjectHandle
|
||||
newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
|
||||
QPDFObjectHandle
|
||||
makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
|
||||
QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
|
||||
QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
|
||||
bool isCached(QPDFObjGen const& og);
|
||||
bool isUnresolved(QPDFObjGen const& og);
|
||||
void updateCache(
|
||||
@ -1205,10 +1170,7 @@ class QPDF
|
||||
std::shared_ptr<InputSource> const& input,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
QPDFExc damagedPDF(
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
QPDFExc damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message);
|
||||
QPDFExc damagedPDF(std::string const& object, std::string const& message);
|
||||
QPDFExc damagedPDF(qpdf_offset_t offset, std::string const& message);
|
||||
QPDFExc damagedPDF(std::string const& message);
|
||||
@ -1223,10 +1185,7 @@ class QPDF
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
bool pipeForeignStreamData(
|
||||
std::shared_ptr<ForeignStreamData>,
|
||||
Pipeline*,
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
std::shared_ptr<ForeignStreamData>, Pipeline*, bool suppress_warnings, bool will_retry);
|
||||
static bool pipeStreamData(
|
||||
std::shared_ptr<QPDF::EncryptionParameters> encp,
|
||||
std::shared_ptr<InputSource> file,
|
||||
@ -1269,31 +1228,24 @@ class QPDF
|
||||
// methods to support page handling
|
||||
|
||||
void getAllPagesInternal(
|
||||
QPDFObjectHandle cur_pages,
|
||||
QPDFObjGen::set& visited,
|
||||
QPDFObjGen::set& seen);
|
||||
QPDFObjectHandle cur_pages, QPDFObjGen::set& visited, QPDFObjGen::set& seen);
|
||||
void insertPage(QPDFObjectHandle newpage, int pos);
|
||||
void flattenPagesTree();
|
||||
void insertPageobjToPage(
|
||||
QPDFObjectHandle const& obj, int pos, bool check_duplicate);
|
||||
void insertPageobjToPage(QPDFObjectHandle const& obj, int pos, bool check_duplicate);
|
||||
|
||||
// methods to support encryption -- implemented in QPDF_encryption.cc
|
||||
static encryption_method_e
|
||||
interpretCF(std::shared_ptr<EncryptionParameters> encp, QPDFObjectHandle);
|
||||
void initializeEncryption();
|
||||
static std::string getKeyForObject(
|
||||
std::shared_ptr<EncryptionParameters> encp,
|
||||
QPDFObjGen const& og,
|
||||
bool use_aes);
|
||||
static std::string
|
||||
getKeyForObject(std::shared_ptr<EncryptionParameters> encp, QPDFObjGen const& og, bool use_aes);
|
||||
void decryptString(std::string&, QPDFObjGen const& og);
|
||||
static std::string compute_encryption_key_from_password(
|
||||
std::string const& password, EncryptionData const& data);
|
||||
static std::string
|
||||
compute_encryption_key_from_password(std::string const& password, EncryptionData const& data);
|
||||
static std::string
|
||||
recover_encryption_key_with_password(std::string const& password, EncryptionData const& data);
|
||||
static std::string recover_encryption_key_with_password(
|
||||
std::string const& password, EncryptionData const& data);
|
||||
static std::string recover_encryption_key_with_password(
|
||||
std::string const& password,
|
||||
EncryptionData const& data,
|
||||
bool& perms_valid);
|
||||
std::string const& password, EncryptionData const& data, bool& perms_valid);
|
||||
static void decryptStream(
|
||||
std::shared_ptr<EncryptionParameters> encp,
|
||||
std::shared_ptr<InputSource> file,
|
||||
@ -1304,12 +1256,10 @@ class QPDF
|
||||
std::vector<std::shared_ptr<Pipeline>>& heap);
|
||||
|
||||
// Methods to support object copying
|
||||
void
|
||||
reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
||||
QPDFObjectHandle replaceForeignIndirectObjects(
|
||||
QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
||||
void
|
||||
copyStreamData(QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
|
||||
void reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
||||
QPDFObjectHandle
|
||||
replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
||||
void copyStreamData(QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
|
||||
|
||||
// Linearization Hint table structures.
|
||||
// Naming conventions:
|
||||
@ -1538,14 +1488,7 @@ class QPDF
|
||||
class ObjUser
|
||||
{
|
||||
public:
|
||||
enum user_e {
|
||||
ou_bad,
|
||||
ou_page,
|
||||
ou_thumb,
|
||||
ou_trailer_key,
|
||||
ou_root_key,
|
||||
ou_root
|
||||
};
|
||||
enum user_e { ou_bad, ou_page, ou_thumb, ou_trailer_key, ou_root_key, ou_root };
|
||||
|
||||
// type is set to ou_bad
|
||||
ObjUser();
|
||||
@ -1598,29 +1541,25 @@ class QPDF
|
||||
bool checkLinearizationInternal();
|
||||
void dumpLinearizationDataInternal();
|
||||
void linearizationWarning(std::string_view);
|
||||
QPDFObjectHandle
|
||||
readHintStream(Pipeline&, qpdf_offset_t offset, size_t length);
|
||||
QPDFObjectHandle readHintStream(Pipeline&, qpdf_offset_t offset, size_t length);
|
||||
void readHPageOffset(BitStream);
|
||||
void readHSharedObject(BitStream);
|
||||
void readHGeneric(BitStream, HGeneric&);
|
||||
qpdf_offset_t maxEnd(ObjUser const& ou);
|
||||
qpdf_offset_t getLinearizationOffset(QPDFObjGen const&);
|
||||
QPDFObjectHandle getUncompressedObject(
|
||||
QPDFObjectHandle&, std::map<int, int> const& object_stream_data);
|
||||
QPDFObjectHandle
|
||||
getUncompressedObject(QPDFObjectHandle&, std::map<int, int> const& object_stream_data);
|
||||
int lengthNextN(int first_object, int n);
|
||||
void checkHPageOffset(
|
||||
std::vector<QPDFObjectHandle> const& pages,
|
||||
std::map<int, int>& idx_to_obj);
|
||||
void checkHSharedObject(
|
||||
std::vector<QPDFObjectHandle> const& pages,
|
||||
std::map<int, int>& idx_to_obj);
|
||||
void
|
||||
checkHPageOffset(std::vector<QPDFObjectHandle> const& pages, std::map<int, int>& idx_to_obj);
|
||||
void
|
||||
checkHSharedObject(std::vector<QPDFObjectHandle> const& pages, std::map<int, int>& idx_to_obj);
|
||||
void checkHOutlines();
|
||||
void dumpHPageOffset();
|
||||
void dumpHSharedObject();
|
||||
void dumpHGeneric(HGeneric&);
|
||||
qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
|
||||
void
|
||||
calculateLinearizationData(std::map<int, int> const& object_stream_data);
|
||||
void calculateLinearizationData(std::map<int, int> const& object_stream_data);
|
||||
void pushOutlinesToPart(
|
||||
std::vector<QPDFObjectHandle>& part,
|
||||
std::set<QPDFObjGen>& lc_outlines,
|
||||
@ -1648,8 +1587,7 @@ class QPDF
|
||||
|
||||
// Methods to support optimization
|
||||
|
||||
void
|
||||
pushInheritedAttributesToPage(bool allow_changes, bool warn_skipped_keys);
|
||||
void pushInheritedAttributesToPage(bool allow_changes, bool warn_skipped_keys);
|
||||
void pushInheritedAttributesToPageInternal(
|
||||
QPDFObjectHandle,
|
||||
std::map<std::string, std::vector<QPDFObjectHandle>>&,
|
||||
@ -1681,11 +1619,7 @@ class QPDF
|
||||
qpdf_json_stream_data_e,
|
||||
std::string const& file_prefix);
|
||||
void writeJSONObject(
|
||||
int version,
|
||||
Pipeline* p,
|
||||
bool& first,
|
||||
std::string const& key,
|
||||
QPDFObjectHandle&);
|
||||
int version, Pipeline* p, bool& first, std::string const& key, QPDFObjectHandle&);
|
||||
|
||||
// Type conversion helper methods
|
||||
template <typename T>
|
||||
|
@ -148,18 +148,15 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
// underlying object will typically be the same as the underlying
|
||||
// object for the field.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
getAnnotationsForField(QPDFFormFieldObjectHelper);
|
||||
std::vector<QPDFAnnotationObjectHelper> getAnnotationsForField(QPDFFormFieldObjectHelper);
|
||||
|
||||
// Return annotations of subtype /Widget for a page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
||||
std::vector<QPDFAnnotationObjectHelper> getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
||||
|
||||
// Return top-level form fields for a page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFFormFieldObjectHelper>
|
||||
getFormFieldsForPage(QPDFPageObjectHelper);
|
||||
std::vector<QPDFFormFieldObjectHelper> getFormFieldsForPage(QPDFPageObjectHelper);
|
||||
|
||||
// Return the terminal field that is associated with this
|
||||
// annotation. If the annotation dictionary is merged with the
|
||||
@ -251,10 +248,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
private:
|
||||
void analyze();
|
||||
void traverseField(
|
||||
QPDFObjectHandle field,
|
||||
QPDFObjectHandle parent,
|
||||
int depth,
|
||||
QPDFObjGen::set& visited);
|
||||
QPDFObjectHandle field, QPDFObjectHandle parent, int depth, QPDFObjGen::set& visited);
|
||||
QPDFObjectHandle getOrCreateAcroForm();
|
||||
void adjustInheritedFields(
|
||||
QPDFObjectHandle obj,
|
||||
@ -264,11 +258,9 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
int from_default_q);
|
||||
void adjustDefaultAppearances(
|
||||
QPDFObjectHandle obj,
|
||||
std::map<std::string, std::map<std::string, std::string>> const&
|
||||
dr_map);
|
||||
std::map<std::string, std::map<std::string, std::string>> const& dr_map);
|
||||
void adjustAppearanceStream(
|
||||
QPDFObjectHandle stream,
|
||||
std::map<std::string, std::map<std::string, std::string>> dr_map);
|
||||
QPDFObjectHandle stream, std::map<std::string, std::map<std::string, std::string>> dr_map);
|
||||
|
||||
class Members
|
||||
{
|
||||
@ -283,8 +275,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
Members(Members const&) = delete;
|
||||
|
||||
bool cache_valid;
|
||||
std::map<QPDFObjGen, std::vector<QPDFAnnotationObjectHelper>>
|
||||
field_to_annotations;
|
||||
std::map<QPDFObjGen, std::vector<QPDFAnnotationObjectHelper>> field_to_annotations;
|
||||
std::map<QPDFObjGen, QPDFFormFieldObjectHelper> annotation_to_field;
|
||||
std::map<QPDFObjGen, std::string> field_to_name;
|
||||
std::map<std::string, std::set<QPDFObjGen>> name_to_fields;
|
||||
|
@ -76,8 +76,7 @@ class QPDFAnnotationObjectHelper: public QPDFObjectHelper
|
||||
// which appearance stream is desired. If not specified, the
|
||||
// appearance state in "/AS" will used.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getAppearanceStream(
|
||||
std::string const& which, std::string const& state = "");
|
||||
QPDFObjectHandle getAppearanceStream(std::string const& which, std::string const& state = "");
|
||||
|
||||
// Generate text suitable for addition to the containing page's
|
||||
// content stream that draws this annotation's appearance stream
|
||||
|
@ -77,10 +77,8 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
|
||||
virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0;
|
||||
// out_data = 0 means to encrypt/decrypt in place
|
||||
QPDF_DLL
|
||||
virtual void RC4_process(
|
||||
unsigned char const* in_data,
|
||||
size_t len,
|
||||
unsigned char* out_data = nullptr) = 0;
|
||||
virtual void
|
||||
RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data = nullptr) = 0;
|
||||
QPDF_DLL
|
||||
virtual void RC4_finalize() = 0;
|
||||
|
||||
@ -93,8 +91,7 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
|
||||
bool cbc_mode,
|
||||
unsigned char* cbc_block) = 0;
|
||||
QPDF_DLL
|
||||
virtual void
|
||||
rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0;
|
||||
virtual void rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0;
|
||||
QPDF_DLL
|
||||
virtual void rijndael_finalize() = 0;
|
||||
};
|
||||
|
@ -78,8 +78,7 @@ class QPDFCryptoProvider
|
||||
|
||||
static QPDFCryptoProvider& getInstance();
|
||||
|
||||
std::shared_ptr<QPDFCryptoImpl>
|
||||
getImpl_internal(std::string const& name) const;
|
||||
std::shared_ptr<QPDFCryptoImpl> getImpl_internal(std::string const& name) const;
|
||||
template <typename T>
|
||||
void registerImpl_internal(std::string const& name);
|
||||
void setDefaultProvider_internal(std::string const& name);
|
||||
|
@ -75,11 +75,9 @@ class QPDFEFStreamObjectHelper: public QPDFObjectHelper
|
||||
// checksum and size are computed automatically and stored. Other
|
||||
// parameters may be supplied using setters defined below.
|
||||
QPDF_DLL
|
||||
static QPDFEFStreamObjectHelper
|
||||
createEFStream(QPDF& qpdf, std::shared_ptr<Buffer> data);
|
||||
static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::shared_ptr<Buffer> data);
|
||||
QPDF_DLL
|
||||
static QPDFEFStreamObjectHelper
|
||||
createEFStream(QPDF& qpdf, std::string const& data);
|
||||
static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::string const& data);
|
||||
// The provider function must write the data to the given
|
||||
// pipeline. The function may be called multiple times by the qpdf
|
||||
// library. You can pass QUtil::file_provider(filename) as the
|
||||
|
@ -48,19 +48,16 @@ class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper
|
||||
bool hasEmbeddedFiles() const;
|
||||
|
||||
QPDF_DLL
|
||||
std::map<std::string, std::shared_ptr<QPDFFileSpecObjectHelper>>
|
||||
getEmbeddedFiles();
|
||||
std::map<std::string, std::shared_ptr<QPDFFileSpecObjectHelper>> getEmbeddedFiles();
|
||||
|
||||
// If an embedded file with the given name exists, return a
|
||||
// (shared) pointer to it. Otherwise, return nullptr.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<QPDFFileSpecObjectHelper>
|
||||
getEmbeddedFile(std::string const& name);
|
||||
std::shared_ptr<QPDFFileSpecObjectHelper> getEmbeddedFile(std::string const& name);
|
||||
|
||||
// Add or replace an attachment
|
||||
QPDF_DLL
|
||||
void replaceEmbeddedFile(
|
||||
std::string const& name, QPDFFileSpecObjectHelper const&);
|
||||
void replaceEmbeddedFile(std::string const& name, QPDFFileSpecObjectHelper const&);
|
||||
|
||||
// Remove an embedded file if present. Return value is true if the
|
||||
// file was present and was removed. This method not only removes
|
||||
|
@ -77,16 +77,16 @@ class QPDFFileSpecObjectHelper: public QPDFObjectHelper
|
||||
// filename, and attach the contents of the specified file as data
|
||||
// in an embedded file stream.
|
||||
QPDF_DLL
|
||||
static QPDFFileSpecObjectHelper createFileSpec(
|
||||
QPDF& qpdf, std::string const& filename, std::string const& fullpath);
|
||||
static QPDFFileSpecObjectHelper
|
||||
createFileSpec(QPDF& qpdf, std::string const& filename, std::string const& fullpath);
|
||||
|
||||
// Create a new filespec as an indirect object with the given
|
||||
// unicode filename and embedded file stream. The file name will
|
||||
// be used as both /UF and /F. If you need to override, call
|
||||
// setFilename.
|
||||
QPDF_DLL
|
||||
static QPDFFileSpecObjectHelper createFileSpec(
|
||||
QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper);
|
||||
static QPDFFileSpecObjectHelper
|
||||
createFileSpec(QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFFileSpecObjectHelper& setDescription(std::string const&);
|
||||
@ -96,8 +96,8 @@ class QPDFFileSpecObjectHelper: public QPDFObjectHelper
|
||||
// QPDFObjectHandle literally, preserving whatever encoding it
|
||||
// might happen to have.
|
||||
QPDF_DLL
|
||||
QPDFFileSpecObjectHelper& setFilename(
|
||||
std::string const& unicode_name, std::string const& compat_name = "");
|
||||
QPDFFileSpecObjectHelper&
|
||||
setFilename(std::string const& unicode_name, std::string const& compat_name = "");
|
||||
|
||||
private:
|
||||
class Members
|
||||
|
@ -183,8 +183,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||
// of a field, use QPDFAcroFormDocumentHelper::setFormFieldName
|
||||
// instead.
|
||||
QPDF_DLL
|
||||
void
|
||||
setFieldAttribute(std::string const& key, std::string const& utf8_value);
|
||||
void setFieldAttribute(std::string const& key, std::string const& utf8_value);
|
||||
|
||||
// Set /V (field value) to the given value. If need_appearances is
|
||||
// true and the field type is either /Tx (text) or /Ch (choice),
|
||||
@ -218,8 +217,7 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||
void setRadioButtonValue(QPDFObjectHandle name);
|
||||
void setCheckBoxValue(bool value);
|
||||
void generateTextAppearance(QPDFAnnotationObjectHelper&);
|
||||
QPDFObjectHandle getFontFromResource(
|
||||
QPDFObjectHandle resources, std::string const& font_name);
|
||||
QPDFObjectHandle getFontFromResource(QPDFObjectHandle resources, std::string const& font_name);
|
||||
|
||||
class Members
|
||||
{
|
||||
|
@ -83,8 +83,7 @@ class QPDFJob
|
||||
// about converting arguments to UTF-8. This method will mutate
|
||||
// arguments that are passed to it.
|
||||
QPDF_DLL
|
||||
void initializeFromArgv(
|
||||
char const* const argv[], char const* progname_env = nullptr);
|
||||
void initializeFromArgv(char const* const argv[], char const* progname_env = nullptr);
|
||||
|
||||
// Initialize a QPDFJob from json. Passing partial = true prevents
|
||||
// this method from doing the final checks (calling
|
||||
@ -132,8 +131,7 @@ class QPDFJob
|
||||
// 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
|
||||
[[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
|
||||
setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||
|
||||
// You can register a custom progress reporter to be called by
|
||||
@ -187,10 +185,7 @@ class QPDFJob
|
||||
|
||||
struct PageSpec
|
||||
{
|
||||
PageSpec(
|
||||
std::string const& filename,
|
||||
char const* password,
|
||||
std::string const& range);
|
||||
PageSpec(std::string const& filename, char const* password, std::string const& range);
|
||||
|
||||
std::string filename;
|
||||
std::shared_ptr<char> password;
|
||||
@ -284,9 +279,7 @@ class QPDFJob
|
||||
Config* endPages();
|
||||
QPDF_DLL
|
||||
PagesConfig* pageSpec(
|
||||
std::string const& filename,
|
||||
std::string const& range,
|
||||
char const* password = nullptr);
|
||||
std::string const& filename, std::string const& range, char const* password = nullptr);
|
||||
|
||||
#include <qpdf/auto_job_c_pages.hh>
|
||||
|
||||
@ -366,10 +359,8 @@ class QPDFJob
|
||||
QPDF_DLL
|
||||
std::shared_ptr<UOConfig> underlay();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<EncConfig> encrypt(
|
||||
int keylen,
|
||||
std::string const& user_password,
|
||||
std::string const& owner_password);
|
||||
std::shared_ptr<EncConfig>
|
||||
encrypt(int keylen, std::string const& user_password, std::string const& owner_password);
|
||||
|
||||
#include <qpdf/auto_job_c_main.hh>
|
||||
|
||||
@ -438,8 +429,7 @@ class QPDFJob
|
||||
// If in verbose mode, call the given function, passing in the
|
||||
// output stream and message prefix.
|
||||
QPDF_DLL
|
||||
void
|
||||
doIfVerbose(std::function<void(Pipeline&, std::string const& prefix)> fn);
|
||||
void doIfVerbose(std::function<void(Pipeline&, std::string const& prefix)> fn);
|
||||
|
||||
// Provide a string that is the help information ("schema" for the
|
||||
// qpdf-specific JSON object) for the specified version of JSON
|
||||
@ -447,16 +437,14 @@ class QPDFJob
|
||||
QPDF_DLL
|
||||
static std::string json_out_schema(int version);
|
||||
|
||||
[[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL
|
||||
json_out_schema_v1();
|
||||
[[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL json_out_schema_v1();
|
||||
|
||||
// Provide a string that is the help information for specified
|
||||
// version of JSON format for QPDFJob.
|
||||
QPDF_DLL
|
||||
static std::string job_json_schema(int version);
|
||||
|
||||
[[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL
|
||||
job_json_schema_v1();
|
||||
[[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1();
|
||||
|
||||
private:
|
||||
struct RotationSpec
|
||||
@ -497,10 +485,8 @@ class QPDFJob
|
||||
|
||||
// Helper functions
|
||||
static void usage(std::string const& msg);
|
||||
static JSON
|
||||
json_schema(int json_version, std::set<std::string>* keys = nullptr);
|
||||
static void parse_object_id(
|
||||
std::string const& objspec, bool& trailer, int& obj, int& gen);
|
||||
static JSON json_schema(int json_version, std::set<std::string>* keys = nullptr);
|
||||
static void parse_object_id(std::string const& objspec, bool& trailer, int& obj, int& gen);
|
||||
void parseRotationParameter(std::string const&);
|
||||
std::vector<int> parseNumrange(char const* range, int max);
|
||||
|
||||
@ -533,12 +519,10 @@ class QPDFJob
|
||||
|
||||
// Transformations
|
||||
void setQPDFOptions(QPDF& pdf);
|
||||
void
|
||||
handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_heap);
|
||||
void handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_heap);
|
||||
bool shouldRemoveUnreferencedResources(QPDF& pdf);
|
||||
void handleRotations(QPDF& pdf);
|
||||
void
|
||||
getUOPagenos(UnderOverlay& uo, std::map<int, std::vector<int>>& pagenos);
|
||||
void getUOPagenos(UnderOverlay& uo, std::map<int, std::vector<int>>& pagenos);
|
||||
void handleUnderOverlay(QPDF& pdf);
|
||||
std::string doUnderOverlayForPage(
|
||||
QPDF& pdf,
|
||||
@ -573,8 +557,7 @@ class QPDFJob
|
||||
// JSON
|
||||
void doJSON(QPDF& pdf, Pipeline*);
|
||||
QPDFObjGen::set getWantedJSONObjects();
|
||||
void doJSONObject(
|
||||
Pipeline* p, bool& first, std::string const& key, QPDFObjectHandle&);
|
||||
void doJSONObject(Pipeline* p, bool& first, std::string const& key, QPDFObjectHandle&);
|
||||
void doJSONObjects(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONPages(Pipeline* p, bool& first, QPDF& pdf);
|
||||
|
@ -153,8 +153,7 @@ class QPDFLogger
|
||||
|
||||
private:
|
||||
QPDFLogger();
|
||||
std::shared_ptr<Pipeline>
|
||||
throwIfNull(std::shared_ptr<Pipeline>, bool null_okay);
|
||||
std::shared_ptr<Pipeline> throwIfNull(std::shared_ptr<Pipeline>, bool null_okay);
|
||||
|
||||
class Members
|
||||
{
|
||||
|
@ -79,8 +79,7 @@ class QPDFMatrix
|
||||
// bounds the polygon resulting from transforming the four
|
||||
// corners.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle::Rectangle
|
||||
transformRectangle(QPDFObjectHandle::Rectangle r) const;
|
||||
QPDFObjectHandle::Rectangle transformRectangle(QPDFObjectHandle::Rectangle r) const;
|
||||
|
||||
// operator== tests for exact equality, not considering deltas for
|
||||
// floating point.
|
||||
|
@ -156,8 +156,7 @@ class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
||||
// Find the entry with the given key. If return_prev_if_not_found
|
||||
// is true and the item is not found, return the next lower item.
|
||||
QPDF_DLL
|
||||
iterator
|
||||
find(std::string const& key, bool return_prev_if_not_found = false);
|
||||
iterator find(std::string const& key, bool return_prev_if_not_found = false);
|
||||
|
||||
// Insert a new item. If the key already exists, it is replaced.
|
||||
QPDF_DLL
|
||||
|
@ -45,8 +45,7 @@ class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
||||
// The qpdf object is required so that this class can issue
|
||||
// warnings, attempt repairs, and add indirect objects.
|
||||
QPDF_DLL
|
||||
QPDFNumberTreeObjectHelper(
|
||||
QPDFObjectHandle, QPDF&, bool auto_repair = true);
|
||||
QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
virtual ~QPDFNumberTreeObjectHelper();
|
||||
@ -82,8 +81,7 @@ class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
||||
// oh to the value with index 3, and set offset to 2 (5 - 3). See
|
||||
// also find().
|
||||
QPDF_DLL
|
||||
bool findObjectAtOrBelow(
|
||||
numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset);
|
||||
bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset);
|
||||
|
||||
class QPDF_DLL_PRIVATE iterator
|
||||
{
|
||||
|
@ -128,22 +128,13 @@ class QPDFObjectHandle
|
||||
// version of the method, which should also return a boolean
|
||||
// indicating whether it ran without errors.
|
||||
QPDF_DLL
|
||||
virtual void
|
||||
provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
|
||||
virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
|
||||
QPDF_DLL
|
||||
virtual bool provideStreamData(
|
||||
QPDFObjGen const& og,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
QPDF_DLL virtual void
|
||||
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
||||
QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
|
||||
QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline);
|
||||
QPDF_DLL virtual bool provideStreamData(
|
||||
int objid,
|
||||
int generation,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
|
||||
QPDF_DLL
|
||||
bool supportsRetry();
|
||||
|
||||
@ -246,8 +237,7 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
virtual void handleObject(QPDFObjectHandle);
|
||||
QPDF_DLL
|
||||
virtual void
|
||||
handleObject(QPDFObjectHandle, size_t offset, size_t length);
|
||||
virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length);
|
||||
|
||||
virtual void handleEOF() = 0;
|
||||
|
||||
@ -408,14 +398,12 @@ class QPDFObjectHandle
|
||||
// True if the object is a dictionary of the specified type and
|
||||
// subtype, if any.
|
||||
QPDF_DLL
|
||||
bool isDictionaryOfType(
|
||||
std::string const& type, std::string const& subtype = "");
|
||||
bool isDictionaryOfType(std::string const& type, std::string const& subtype = "");
|
||||
|
||||
// True if the object is a stream of the specified type and
|
||||
// subtype, if any.
|
||||
QPDF_DLL
|
||||
bool
|
||||
isStreamOfType(std::string const& type, std::string const& subtype = "");
|
||||
bool isStreamOfType(std::string const& type, std::string const& subtype = "");
|
||||
|
||||
// Public factory methods
|
||||
|
||||
@ -433,9 +421,8 @@ class QPDFObjectHandle
|
||||
// in the message of any QPDFExc exception thrown for invalid
|
||||
// syntax. See also the global `operator ""_qpdf` defined below.
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle parse(
|
||||
std::string const& object_str,
|
||||
std::string const& object_description = "");
|
||||
static QPDFObjectHandle
|
||||
parse(std::string const& object_str, std::string const& object_description = "");
|
||||
|
||||
// Construct an object of any type from a string representation of
|
||||
// the object. Indirect object syntax (obj gen R) is allowed and
|
||||
@ -447,10 +434,8 @@ class QPDFObjectHandle
|
||||
// object, which will just be the first number and will report
|
||||
// that there is trailing data at the end of the string.
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle parse(
|
||||
QPDF* context,
|
||||
std::string const& object_str,
|
||||
std::string const& object_description = "");
|
||||
static QPDFObjectHandle
|
||||
parse(QPDF* context, std::string const& object_str, std::string const& object_description = "");
|
||||
|
||||
// Construct an object as above by reading from the given
|
||||
// InputSource at its current position and using the tokenizer you
|
||||
@ -480,8 +465,7 @@ class QPDFObjectHandle
|
||||
// error messages will also be more useful because the page object
|
||||
// information will be known.
|
||||
QPDF_DLL
|
||||
static void parseContentStream(
|
||||
QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks);
|
||||
static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks);
|
||||
|
||||
// When called on a stream or stream array that is some page's
|
||||
// content streams, do the same as pipePageContents. This method
|
||||
@ -500,10 +484,8 @@ class QPDFObjectHandle
|
||||
// Pl_Concatenate and then call manualFinish() on the
|
||||
// Pl_Concatenate pipeline at the end.
|
||||
QPDF_DLL
|
||||
void pipeContentStreams(
|
||||
Pipeline* p,
|
||||
std::string const& description,
|
||||
std::string& all_description);
|
||||
void
|
||||
pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description);
|
||||
|
||||
// As of qpdf 8, it is possible to add custom token filters to a
|
||||
// stream. The tokenized stream data is passed through the token
|
||||
@ -554,8 +536,8 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newReal(std::string const& value);
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newReal(
|
||||
double value, int decimal_places = 0, bool trim_trailing_zeroes = true);
|
||||
static QPDFObjectHandle
|
||||
newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true);
|
||||
// Note about name objects: qpdf's internal representation of a
|
||||
// PDF name is a sequence of bytes, excluding the NUL character,
|
||||
// and starting with a slash. Name objects as represented in the
|
||||
@ -591,8 +573,7 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newArray();
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle
|
||||
newArray(std::vector<QPDFObjectHandle> const& items);
|
||||
static QPDFObjectHandle newArray(std::vector<QPDFObjectHandle> const& items);
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newArray(Rectangle const&);
|
||||
QPDF_DLL
|
||||
@ -602,8 +583,7 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newDictionary();
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle
|
||||
newDictionary(std::map<std::string, QPDFObjectHandle> const& items);
|
||||
static QPDFObjectHandle newDictionary(std::map<std::string, QPDFObjectHandle> const& items);
|
||||
|
||||
// Create an array from a rectangle. Equivalent to the rectangle
|
||||
// form of newArray.
|
||||
@ -686,8 +666,7 @@ class QPDFObjectHandle
|
||||
// else. To add objects from another qpdf, use copyForeignObject
|
||||
// instead.
|
||||
QPDF_DLL
|
||||
void setObjectDescription(
|
||||
QPDF* owning_qpdf, std::string const& object_description);
|
||||
void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
|
||||
QPDF_DLL
|
||||
bool hasObjectDescription();
|
||||
|
||||
@ -964,8 +943,7 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
void mergeResources(
|
||||
QPDFObjectHandle other,
|
||||
std::map<std::string, std::map<std::string, std::string>>* conflicts =
|
||||
nullptr);
|
||||
std::map<std::string, std::map<std::string, std::string>>* conflicts = nullptr);
|
||||
|
||||
// Get all resource names from a resource dictionary. If this
|
||||
// object is a dictionary, this method returns a set of all the
|
||||
@ -1118,13 +1096,11 @@ class QPDFObjectHandle
|
||||
void replaceKey(std::string const& key, QPDFObjectHandle const& value);
|
||||
// Replace value of key and return the value.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value);
|
||||
QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value);
|
||||
// Replace value of key and return the old value, or null if the
|
||||
// key was previously not present.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value);
|
||||
QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value);
|
||||
// Remove key, doing nothing if key does not exist.
|
||||
QPDF_DLL
|
||||
void removeKey(std::string const& key);
|
||||
@ -1167,8 +1143,7 @@ class QPDFObjectHandle
|
||||
// Returns filtered (uncompressed) stream data. Throws an
|
||||
// exception if the stream is filtered and we can't decode it.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Buffer>
|
||||
getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized);
|
||||
std::shared_ptr<Buffer> getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized);
|
||||
|
||||
// Returns unfiltered (raw) stream data.
|
||||
QPDF_DLL
|
||||
@ -1347,8 +1322,7 @@ class QPDFObjectHandle
|
||||
// returning true if it succeeded without errors.
|
||||
QPDF_DLL
|
||||
void replaceStreamData(
|
||||
std::function<bool(Pipeline*, bool suppress_warnings, bool will_retry)>
|
||||
provider,
|
||||
std::function<bool(Pipeline*, bool suppress_warnings, bool will_retry)> provider,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
|
||||
@ -1615,15 +1589,14 @@ class QPDFObjectHandle
|
||||
void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams);
|
||||
void disconnect();
|
||||
void setParsedOffset(qpdf_offset_t offset);
|
||||
void parseContentStream_internal(
|
||||
std::string const& description, ParserCallbacks* callbacks);
|
||||
void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks);
|
||||
static void parseContentStream_data(
|
||||
std::shared_ptr<Buffer>,
|
||||
std::string const& description,
|
||||
ParserCallbacks* callbacks,
|
||||
QPDF* context);
|
||||
std::vector<QPDFObjectHandle> arrayOrStreamToStreamArray(
|
||||
std::string const& description, std::string& all_description);
|
||||
std::vector<QPDFObjectHandle>
|
||||
arrayOrStreamToStreamArray(std::string const& description, std::string& all_description);
|
||||
static void warn(QPDF*, QPDFExc const&);
|
||||
void checkOwnership(QPDFObjectHandle const&) const;
|
||||
|
||||
|
@ -104,10 +104,7 @@ class QPDFPageDocumentHelper: public QPDFDocumentHelper
|
||||
// Add new page before or after refpage. See comments for addPage
|
||||
// for details about what newpage should be.
|
||||
QPDF_DLL
|
||||
void addPageAt(
|
||||
QPDFPageObjectHelper newpage,
|
||||
bool before,
|
||||
QPDFPageObjectHelper refpage);
|
||||
void addPageAt(QPDFPageObjectHelper newpage, bool before, QPDFPageObjectHelper refpage);
|
||||
|
||||
// Remove page from the pdf.
|
||||
QPDF_DLL
|
||||
@ -125,8 +122,7 @@ class QPDFPageDocumentHelper: public QPDFDocumentHelper
|
||||
// comments there in QPDFAnnotationObjectHelper.hh for meanings of
|
||||
// those flags.
|
||||
QPDF_DLL
|
||||
void flattenAnnotations(
|
||||
int required_flags = 0, int forbidden_flags = an_invisible | an_hidden);
|
||||
void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden);
|
||||
|
||||
private:
|
||||
void flattenAnnotationsForPage(
|
||||
|
@ -170,26 +170,22 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
// Return the effective CropBox. If not defined, fall back to
|
||||
// MediaBox
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
QPDFObjectHandle getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Return the effective BleedBox. If not defined, fall back to
|
||||
// CropBox.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
QPDFObjectHandle getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Return the effective TrimBox. If not defined, fall back to
|
||||
// CropBox.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
QPDFObjectHandle getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Return the effective ArtBox. If not defined, fall back to
|
||||
// CropBox.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle
|
||||
getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
QPDFObjectHandle getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Iterate through XObjects, possibly recursing into form
|
||||
// XObjects. This works with pages or form XObjects. Call action
|
||||
@ -203,26 +199,20 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
void forEachXObject(
|
||||
bool recursive,
|
||||
std::function<void(
|
||||
QPDFObjectHandle& obj,
|
||||
QPDFObjectHandle& xobj_dict,
|
||||
std::string const& key)> action,
|
||||
QPDFObjectHandle& obj, QPDFObjectHandle& xobj_dict, std::string const& key)> action,
|
||||
std::function<bool(QPDFObjectHandle)> selector = nullptr);
|
||||
// Only call action for images
|
||||
QPDF_DLL
|
||||
void forEachImage(
|
||||
bool recursive,
|
||||
std::function<void(
|
||||
QPDFObjectHandle& obj,
|
||||
QPDFObjectHandle& xobj_dict,
|
||||
std::string const& key)> action);
|
||||
QPDFObjectHandle& obj, QPDFObjectHandle& xobj_dict, std::string const& key)> action);
|
||||
// Only call action for form XObjects
|
||||
QPDF_DLL
|
||||
void forEachFormXObject(
|
||||
bool recursive,
|
||||
std::function<void(
|
||||
QPDFObjectHandle& obj,
|
||||
QPDFObjectHandle& xobj_dict,
|
||||
std::string const& key)> action);
|
||||
QPDFObjectHandle& obj, QPDFObjectHandle& xobj_dict, std::string const& key)> action);
|
||||
|
||||
// Returns an empty map if there are no images or no resources.
|
||||
// Prior to qpdf 8.4.0, this function did not support inherited
|
||||
@ -258,8 +248,7 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
// only_subtype is non-empty, only include annotations of the
|
||||
// given subtype.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper>
|
||||
getAnnotations(std::string const& only_subtype = "");
|
||||
std::vector<QPDFAnnotationObjectHelper> getAnnotations(std::string const& only_subtype = "");
|
||||
|
||||
// Returns a vector of stream objects representing the content
|
||||
// streams for the given page. This routine allows the caller to
|
||||
@ -319,13 +308,11 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
// contents, as happens with addContentTokenFilter. See
|
||||
// examples/pdf-count-strings.cc for an example.
|
||||
QPDF_DLL
|
||||
void filterContents(
|
||||
QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
void filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
|
||||
// Old name -- calls filterContents()
|
||||
QPDF_DLL
|
||||
void filterPageContents(
|
||||
QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
void filterPageContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
|
||||
// Pipe a page's contents through the given pipeline. This method
|
||||
// works whether the contents are a single stream or an array of
|
||||
@ -341,8 +328,7 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
// The token filter is applied to the page's contents as a single
|
||||
// stream. Also works on form XObjects.
|
||||
QPDF_DLL
|
||||
void addContentTokenFilter(
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter> token_filter);
|
||||
void addContentTokenFilter(std::shared_ptr<QPDFObjectHandle::TokenFilter> token_filter);
|
||||
|
||||
// A page's resources dictionary maps names to objects elsewhere
|
||||
// in the file. This method walks through a page's contents and
|
||||
@ -500,8 +486,8 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
bool copy_if_shared,
|
||||
std::function<QPDFObjectHandle()> get_fallback,
|
||||
bool copy_if_fallback);
|
||||
static bool removeUnreferencedResourcesHelper(
|
||||
QPDFPageObjectHelper ph, std::set<std::string>& unresolved);
|
||||
static bool
|
||||
removeUnreferencedResourcesHelper(QPDFPageObjectHelper ph, std::set<std::string>& unresolved);
|
||||
|
||||
class Members
|
||||
{
|
||||
|
@ -48,8 +48,7 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
static std::string
|
||||
createWhat(std::string const& description, int system_errno);
|
||||
static std::string createWhat(std::string const& description, int system_errno);
|
||||
|
||||
// This class does not use the Members pattern to avoid needless
|
||||
// memory allocations during exception handling.
|
||||
|
@ -104,8 +104,7 @@ class QPDFTokenizer
|
||||
{
|
||||
// Ignore fields other than type and value
|
||||
return (
|
||||
(this->type != tt_bad) && (this->type == rhs.type) &&
|
||||
(this->value == rhs.value));
|
||||
(this->type != tt_bad) && (this->type == rhs.type) && (this->value == rhs.value));
|
||||
}
|
||||
bool
|
||||
isInteger() const
|
||||
@ -216,8 +215,7 @@ class QPDFTokenizer
|
||||
// beginning of the token. Returns false if the token is bad
|
||||
// or if scanning produced an error message for any reason.
|
||||
|
||||
bool nextToken(
|
||||
InputSource& input, std::string const& context, size_t max_len = 0);
|
||||
bool nextToken(InputSource& input, std::string const& context, size_t max_len = 0);
|
||||
|
||||
// The following methods are only valid after nextToken has been called
|
||||
// and until another QPDFTokenizer method is called. They allow the results
|
||||
@ -317,8 +315,7 @@ QPDFTokenizer::getType() const noexcept
|
||||
inline std::string const&
|
||||
QPDFTokenizer::getValue() const noexcept
|
||||
{
|
||||
return (this->type == tt_name || this->type == tt_string) ? this->val
|
||||
: this->raw_val;
|
||||
return (this->type == tt_name || this->type == tt_string) ? this->val : this->raw_val;
|
||||
}
|
||||
inline std::string const&
|
||||
QPDFTokenizer::getRawValue() const noexcept
|
||||
|
@ -561,16 +561,11 @@ class QPDFWriter
|
||||
void writePad(size_t nspaces);
|
||||
void assignCompressedObjectNumbers(QPDFObjGen const& og);
|
||||
void enqueueObject(QPDFObjectHandle object);
|
||||
void writeObjectStreamOffsets(
|
||||
std::vector<qpdf_offset_t>& offsets, int first_obj);
|
||||
void writeObjectStreamOffsets(std::vector<qpdf_offset_t>& offsets, int first_obj);
|
||||
void writeObjectStream(QPDFObjectHandle object);
|
||||
void writeObject(QPDFObjectHandle object, int object_stream_index = -1);
|
||||
void writeTrailer(
|
||||
trailer_e which,
|
||||
int size,
|
||||
bool xref_stream,
|
||||
qpdf_offset_t prev,
|
||||
int linearization_pass);
|
||||
trailer_e which, int size, bool xref_stream, qpdf_offset_t prev, int linearization_pass);
|
||||
bool willFilterStream(
|
||||
QPDFObjectHandle stream,
|
||||
bool& compress_stream,
|
||||
@ -601,8 +596,7 @@ class QPDFWriter
|
||||
bool allow_modify_other,
|
||||
qpdf_r3_print_e print,
|
||||
qpdf_r3_modify_e modify);
|
||||
void
|
||||
disableIncompatibleEncryption(int major, int minor, int extension_level);
|
||||
void disableIncompatibleEncryption(int major, int minor, int extension_level);
|
||||
void parseVersion(std::string const& version, int& major, int& minor) const;
|
||||
int compareVersions(int major1, int minor1, int major2, int minor2) const;
|
||||
void setEncryptionParameters(
|
||||
@ -640,8 +634,7 @@ class QPDFWriter
|
||||
void doWriteSetup();
|
||||
void writeHeader();
|
||||
void writeHintStream(int hint_id);
|
||||
qpdf_offset_t
|
||||
writeXRefTable(trailer_e which, int first, int last, int size);
|
||||
qpdf_offset_t writeXRefTable(trailer_e which, int first, int last, int size);
|
||||
qpdf_offset_t writeXRefTable(
|
||||
trailer_e which,
|
||||
int first,
|
||||
@ -693,8 +686,7 @@ class QPDFWriter
|
||||
void pushMD5Pipeline(PipelinePopper&);
|
||||
void computeDeterministicIDData();
|
||||
|
||||
void discardGeneration(
|
||||
std::map<QPDFObjGen, int> const& in, std::map<int, int>& out);
|
||||
void discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, int>& out);
|
||||
|
||||
class Members
|
||||
{
|
||||
|
@ -49,11 +49,9 @@ namespace QUtil
|
||||
QPDF_DLL
|
||||
std::string int_to_string_base(long long, int base, int length = 0);
|
||||
QPDF_DLL
|
||||
std::string
|
||||
uint_to_string_base(unsigned long long, int base, int length = 0);
|
||||
std::string uint_to_string_base(unsigned long long, int base, int length = 0);
|
||||
QPDF_DLL
|
||||
std::string double_to_string(
|
||||
double, int decimal_places = 0, bool trim_trailing_zeroes = true);
|
||||
std::string double_to_string(double, int decimal_places = 0, bool trim_trailing_zeroes = true);
|
||||
|
||||
// These string to number methods throw std::runtime_error on
|
||||
// underflow/overflow.
|
||||
@ -257,14 +255,7 @@ namespace QUtil
|
||||
QPDFTime() = default;
|
||||
QPDFTime(QPDFTime const&) = default;
|
||||
QPDFTime& operator=(QPDFTime const&) = default;
|
||||
QPDFTime(
|
||||
int year,
|
||||
int month,
|
||||
int day,
|
||||
int hour,
|
||||
int minute,
|
||||
int second,
|
||||
int tz_delta) :
|
||||
QPDFTime(int year, int month, int day, int hour, int minute, int second, int tz_delta) :
|
||||
year(year),
|
||||
month(month),
|
||||
day(day),
|
||||
@ -331,8 +322,7 @@ namespace QUtil
|
||||
// to pass a value of pos that is greater than or equal to the
|
||||
// length of the string.
|
||||
QPDF_DLL
|
||||
unsigned long get_next_utf8_codepoint(
|
||||
std::string const& utf8_val, size_t& pos, bool& error);
|
||||
unsigned long get_next_utf8_codepoint(std::string const& utf8_val, size_t& pos, bool& error);
|
||||
|
||||
// Test whether this is a UTF-16 string. This is indicated by
|
||||
// first two bytes being 0xFE 0xFF (big-endian) or 0xFF 0xFE
|
||||
@ -360,30 +350,23 @@ namespace QUtil
|
||||
QPDF_DLL
|
||||
std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
std::string
|
||||
utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?');
|
||||
std::string utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
std::string
|
||||
utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?');
|
||||
std::string utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
std::string
|
||||
utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?');
|
||||
std::string utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?');
|
||||
|
||||
// These versions return true if the conversion was successful and
|
||||
// false if any unrepresentable characters were found and had to
|
||||
// be substituted with the unknown character.
|
||||
QPDF_DLL
|
||||
bool utf8_to_ascii(
|
||||
std::string const& utf8, std::string& ascii, char unknown_char = '?');
|
||||
bool utf8_to_ascii(std::string const& utf8, std::string& ascii, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
bool utf8_to_win_ansi(
|
||||
std::string const& utf8, std::string& win, char unknown_char = '?');
|
||||
bool utf8_to_win_ansi(std::string const& utf8, std::string& win, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
bool utf8_to_mac_roman(
|
||||
std::string const& utf8, std::string& mac, char unknown_char = '?');
|
||||
bool utf8_to_mac_roman(std::string const& utf8, std::string& mac, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
bool utf8_to_pdf_doc(
|
||||
std::string const& utf8, std::string& pdfdoc, char unknown_char = '?');
|
||||
bool utf8_to_pdf_doc(std::string const& utf8, std::string& pdfdoc, char unknown_char = '?');
|
||||
|
||||
// Convert a UTF-16 encoded string to UTF-8. Unrepresentable code
|
||||
// points are converted to U+FFFD.
|
||||
@ -412,10 +395,7 @@ namespace QUtil
|
||||
// about everything else) accepts UTF-16LE (as of 10.6.2).
|
||||
QPDF_DLL
|
||||
void analyze_encoding(
|
||||
std::string const& str,
|
||||
bool& has_8bit_chars,
|
||||
bool& is_valid_utf8,
|
||||
bool& is_utf16);
|
||||
std::string const& str, bool& has_8bit_chars, bool& is_valid_utf8, bool& is_utf16);
|
||||
|
||||
// Try to compensate for previously incorrectly encoded strings.
|
||||
// We want to compensate for the following errors:
|
||||
@ -472,14 +452,11 @@ namespace QUtil
|
||||
// Filename is UTF-8 encoded, even on Windows, as described in the
|
||||
// comments for safe_fopen.
|
||||
QPDF_DLL
|
||||
std::list<std::string>
|
||||
read_lines_from_file(char const* filename, bool preserve_eol = false);
|
||||
std::list<std::string> read_lines_from_file(char const* filename, bool preserve_eol = false);
|
||||
QPDF_DLL
|
||||
std::list<std::string>
|
||||
read_lines_from_file(std::istream&, bool preserve_eol = false);
|
||||
std::list<std::string> read_lines_from_file(std::istream&, bool preserve_eol = false);
|
||||
QPDF_DLL
|
||||
std::list<std::string>
|
||||
read_lines_from_file(FILE*, bool preserve_eol = false);
|
||||
std::list<std::string> read_lines_from_file(FILE*, bool preserve_eol = false);
|
||||
QPDF_DLL
|
||||
void read_lines_from_file(
|
||||
std::function<bool(char&)> next_char,
|
||||
@ -487,8 +464,7 @@ namespace QUtil
|
||||
bool preserve_eol = false);
|
||||
|
||||
QPDF_DLL
|
||||
void read_file_into_memory(
|
||||
char const* filename, std::shared_ptr<char>& file_buf, size_t& size);
|
||||
void read_file_into_memory(char const* filename, std::shared_ptr<char>& file_buf, size_t& size);
|
||||
|
||||
QPDF_DLL
|
||||
std::string read_file_into_string(char const* filename);
|
||||
@ -532,8 +508,7 @@ namespace QUtil
|
||||
// invoked, convert all UTF-16 encoded strings to UTF-8, and call
|
||||
// another main.
|
||||
QPDF_DLL
|
||||
int call_main_from_wmain(
|
||||
int argc, wchar_t* argv[], std::function<int(int, char*[])> realmain);
|
||||
int call_main_from_wmain(int argc, wchar_t* argv[], std::function<int(int, char*[])> realmain);
|
||||
QPDF_DLL
|
||||
int call_main_from_wmain(
|
||||
int argc,
|
||||
@ -561,8 +536,7 @@ QUtil::is_hex_digit(char ch)
|
||||
inline bool
|
||||
QUtil::is_space(char ch)
|
||||
{
|
||||
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' ||
|
||||
ch == '\v';
|
||||
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\v';
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -603,8 +577,7 @@ inline std::string
|
||||
QUtil::hex_encode_char(char c)
|
||||
{
|
||||
static auto constexpr hexchars = "0123456789abcdef";
|
||||
return {
|
||||
'#', hexchars[static_cast<unsigned char>(c) >> 4], hexchars[c & 0x0f]};
|
||||
return {'#', hexchars[static_cast<unsigned char>(c) >> 4], hexchars[c & 0x0f]};
|
||||
}
|
||||
|
||||
inline constexpr char
|
||||
@ -612,8 +585,7 @@ QUtil::hex_decode_char(char digit) noexcept
|
||||
{
|
||||
return digit <= '9' && digit >= '0'
|
||||
? char(digit - '0')
|
||||
: (digit >= 'a' ? char(digit - 'a' + 10)
|
||||
: (digit >= 'A' ? char(digit - 'A' + 10) : '\20'));
|
||||
: (digit >= 'a' ? char(digit - 'a' + 10) : (digit >= 'A' ? char(digit - 'A' + 10) : '\20'));
|
||||
}
|
||||
|
||||
#endif // QUTIL_HH
|
||||
|
@ -326,8 +326,7 @@ extern "C" {
|
||||
*/
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_create_from_json_data(
|
||||
qpdf_data qpdf, char const* buffer, unsigned long long size);
|
||||
qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size);
|
||||
|
||||
/* JSON UPDATE FUNCTIONS */
|
||||
|
||||
@ -341,8 +340,7 @@ extern "C" {
|
||||
qpdf_update_from_json_file(qpdf_data qpdf, char const* filename);
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_update_from_json_data(
|
||||
qpdf_data qpdf, char const* buffer, unsigned long long size);
|
||||
qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size);
|
||||
|
||||
/* READ FUNCTIONS */
|
||||
|
||||
@ -492,23 +490,19 @@ extern "C" {
|
||||
unsigned char const* qpdf_get_buffer(qpdf_data qpdf);
|
||||
|
||||
QPDF_DLL
|
||||
void
|
||||
qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode);
|
||||
void qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode);
|
||||
|
||||
QPDF_DLL
|
||||
void
|
||||
qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode);
|
||||
void qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_decode_level(
|
||||
qpdf_data qpdf, enum qpdf_stream_decode_level_e level);
|
||||
void qpdf_set_decode_level(qpdf_data qpdf, enum qpdf_stream_decode_level_e level);
|
||||
|
||||
QPDF_DLL
|
||||
void
|
||||
qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value);
|
||||
void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value);
|
||||
@ -625,8 +619,8 @@ extern "C" {
|
||||
void qpdf_force_pdf_version(qpdf_data qpdf, char const* version);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_force_pdf_version_and_extension(
|
||||
qpdf_data qpdf, char const* version, int extension_level);
|
||||
void
|
||||
qpdf_force_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level);
|
||||
|
||||
/* During write, your report_progress function will be called with
|
||||
* a value between 0 and 100 representing the approximate write
|
||||
@ -640,9 +634,7 @@ extern "C" {
|
||||
*/
|
||||
QPDF_DLL
|
||||
void qpdf_register_progress_reporter(
|
||||
qpdf_data qpdf,
|
||||
void (*report_progress)(int percent, void* data),
|
||||
void* data);
|
||||
qpdf_data qpdf, void (*report_progress)(int percent, void* data), void* data);
|
||||
|
||||
/* Do actual write operation. */
|
||||
QPDF_DLL
|
||||
@ -733,8 +725,7 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
void
|
||||
qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh);
|
||||
void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh);
|
||||
|
||||
/* Wrappers around QPDFObjectHandle methods. Be sure to read
|
||||
* corresponding comments in QPDFObjectHandle.hh to understand
|
||||
@ -811,8 +802,7 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_oh_get_value_as_ulonglong(
|
||||
qpdf_data qpdf, qpdf_oh oh, unsigned long long* value);
|
||||
QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value);
|
||||
QPDF_DLL
|
||||
unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
@ -822,8 +812,8 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_oh_get_value_as_real(
|
||||
qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
QPDF_BOOL
|
||||
qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh);
|
||||
@ -836,8 +826,8 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_oh_get_value_as_name(
|
||||
qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
QPDF_BOOL
|
||||
qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
|
||||
/* Return the length of the last string returned. This enables you
|
||||
* to retrieve the entire string for cases in which a char*
|
||||
@ -858,19 +848,17 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_oh_get_value_as_string(
|
||||
qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
QPDF_BOOL
|
||||
qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
QPDF_DLL
|
||||
char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh);
|
||||
QPDF_DLL
|
||||
QPDF_BOOL qpdf_oh_get_value_as_utf8(
|
||||
qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
QPDF_BOOL
|
||||
qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||
QPDF_DLL
|
||||
char const*
|
||||
qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
||||
char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
||||
QPDF_DLL
|
||||
char const*
|
||||
qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
||||
char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
||||
|
||||
QPDF_DLL
|
||||
int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh);
|
||||
@ -906,8 +894,7 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||
QPDF_DLL
|
||||
qpdf_oh
|
||||
qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||
qpdf_oh qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||
|
||||
QPDF_DLL
|
||||
QPDF_BOOL
|
||||
@ -924,8 +911,7 @@ extern "C" {
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value);
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_new_real_from_double(
|
||||
qpdf_data qpdf, double value, int decimal_places);
|
||||
qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf, double value, int decimal_places);
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name);
|
||||
QPDF_DLL
|
||||
@ -936,11 +922,9 @@ extern "C" {
|
||||
* contain atrbitary binary data including embedded null characters.
|
||||
*/
|
||||
QPDF_DLL
|
||||
qpdf_oh
|
||||
qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length);
|
||||
qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length);
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_new_binary_unicode_string(
|
||||
qpdf_data qpdf, char const* str, size_t length);
|
||||
qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* str, size_t length);
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_new_array(qpdf_data qpdf);
|
||||
QPDF_DLL
|
||||
@ -959,8 +943,7 @@ extern "C" {
|
||||
void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh);
|
||||
|
||||
QPDF_DLL
|
||||
void
|
||||
qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
|
||||
void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
|
||||
QPDF_DLL
|
||||
void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
|
||||
QPDF_DLL
|
||||
@ -969,13 +952,11 @@ extern "C" {
|
||||
void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_oh_replace_key(
|
||||
qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item);
|
||||
void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item);
|
||||
QPDF_DLL
|
||||
void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||
QPDF_DLL
|
||||
void qpdf_oh_replace_or_remove_key(
|
||||
qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item);
|
||||
void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item);
|
||||
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh);
|
||||
@ -1005,8 +986,7 @@ extern "C" {
|
||||
* while `foreign_oh` belongs to `other_qpdf`.
|
||||
*/
|
||||
QPDF_DLL
|
||||
qpdf_oh qpdf_oh_copy_foreign_object(
|
||||
qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh);
|
||||
qpdf_oh qpdf_oh_copy_foreign_object(qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh);
|
||||
|
||||
/* STREAM FUNCTIONS */
|
||||
|
||||
@ -1105,19 +1085,12 @@ extern "C" {
|
||||
|
||||
/* addPage() */
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_add_page(
|
||||
qpdf_data qpdf,
|
||||
qpdf_data newpage_qpdf,
|
||||
qpdf_oh newpage,
|
||||
QPDF_BOOL first);
|
||||
QPDF_ERROR_CODE
|
||||
qpdf_add_page(qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first);
|
||||
/* addPageAt() */
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_add_page_at(
|
||||
qpdf_data qpdf,
|
||||
qpdf_data newpage_qpdf,
|
||||
qpdf_oh newpage,
|
||||
QPDF_BOOL before,
|
||||
qpdf_oh refpage);
|
||||
qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL before, qpdf_oh refpage);
|
||||
/* removePage() */
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page);
|
||||
|
@ -111,8 +111,7 @@ extern "C" {
|
||||
* is invalid to call any other functions this job handle.
|
||||
*/
|
||||
QPDF_DLL
|
||||
int
|
||||
qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]);
|
||||
int qpdfjob_initialize_from_argv(qpdfjob_handle j, char const* const argv[]);
|
||||
|
||||
#ifndef QPDF_NO_WCHAR_T
|
||||
/* This function is the same as qpdfjob_initialize_from_argv
|
||||
@ -120,8 +119,7 @@ extern "C" {
|
||||
* suitable for calling from a Windows wmain function.
|
||||
*/
|
||||
QPDF_DLL
|
||||
int qpdfjob_initialize_from_wide_argv(
|
||||
qpdfjob_handle j, wchar_t const* const argv[]);
|
||||
int qpdfjob_initialize_from_wide_argv(qpdfjob_handle j, wchar_t const* const argv[]);
|
||||
#endif /* QPDF_NO_WCHAR_T */
|
||||
|
||||
/* This function wraps QPDFJob::initializeFromJson. The return
|
||||
@ -167,9 +165,7 @@ extern "C" {
|
||||
*/
|
||||
QPDF_DLL
|
||||
void qpdfjob_register_progress_reporter(
|
||||
qpdfjob_handle j,
|
||||
void (*report_progress)(int percent, void* data),
|
||||
void* data);
|
||||
qpdfjob_handle j, void (*report_progress)(int percent, void* data), void* data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -76,22 +76,13 @@ extern "C" {
|
||||
|
||||
QPDF_DLL
|
||||
void qpdflogger_set_info(
|
||||
qpdflogger_handle l,
|
||||
enum qpdf_log_dest_e dest,
|
||||
qpdf_log_fn_t fn,
|
||||
void* udata);
|
||||
qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata);
|
||||
QPDF_DLL
|
||||
void qpdflogger_set_warn(
|
||||
qpdflogger_handle l,
|
||||
enum qpdf_log_dest_e dest,
|
||||
qpdf_log_fn_t fn,
|
||||
void* udata);
|
||||
qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata);
|
||||
QPDF_DLL
|
||||
void qpdflogger_set_error(
|
||||
qpdflogger_handle l,
|
||||
enum qpdf_log_dest_e dest,
|
||||
qpdf_log_fn_t fn,
|
||||
void* udata);
|
||||
qpdflogger_handle l, enum qpdf_log_dest_e dest, qpdf_log_fn_t fn, void* udata);
|
||||
|
||||
/* A non-zero value for only_if_not_set means that the save
|
||||
* pipeline will only be changed if it is not already set.
|
||||
@ -104,8 +95,7 @@ extern "C" {
|
||||
void* udata,
|
||||
int only_if_not_set);
|
||||
QPDF_DLL
|
||||
void qpdflogger_save_to_standard_output(
|
||||
qpdflogger_handle l, int only_if_not_set);
|
||||
void qpdflogger_save_to_standard_output(qpdflogger_handle l, int only_if_not_set);
|
||||
|
||||
/* For testing */
|
||||
QPDF_DLL
|
||||
|
@ -27,11 +27,9 @@ AES_PDF_native::AES_PDF_native(
|
||||
std::memcpy(this->key.get(), key, key_bytes);
|
||||
std::memset(this->rk.get(), 0, rk_bytes);
|
||||
if (encrypt) {
|
||||
this->nrounds =
|
||||
rijndaelSetupEncrypt(this->rk.get(), this->key.get(), keybits);
|
||||
this->nrounds = rijndaelSetupEncrypt(this->rk.get(), this->key.get(), keybits);
|
||||
} else {
|
||||
this->nrounds =
|
||||
rijndaelSetupDecrypt(this->rk.get(), this->key.get(), keybits);
|
||||
this->nrounds = rijndaelSetupDecrypt(this->rk.get(), this->key.get(), keybits);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +44,7 @@ AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
|
||||
}
|
||||
rijndaelEncrypt(this->rk.get(), this->nrounds, in_data, out_data);
|
||||
if (this->cbc_mode) {
|
||||
memcpy(
|
||||
this->cbc_block, out_data, QPDFCryptoImpl::rijndael_buf_size);
|
||||
memcpy(this->cbc_block, out_data, QPDFCryptoImpl::rijndael_buf_size);
|
||||
}
|
||||
} else {
|
||||
rijndaelDecrypt(this->rk.get(), this->nrounds, in_data, out_data);
|
||||
|
@ -33,8 +33,7 @@ BitStream::getBits(size_t nbits)
|
||||
long long
|
||||
BitStream::getBitsSigned(size_t nbits)
|
||||
{
|
||||
unsigned long long bits =
|
||||
read_bits(this->p, this->bit_offset, this->bits_available, nbits);
|
||||
unsigned long long bits = read_bits(this->p, this->bit_offset, this->bits_available, nbits);
|
||||
long long result = 0;
|
||||
if (static_cast<long long>(bits) > 1LL << (nbits - 1)) {
|
||||
result = static_cast<long long>(bits - (1ULL << nbits));
|
||||
@ -49,8 +48,7 @@ BitStream::getBitsInt(size_t nbits)
|
||||
{
|
||||
return static_cast<int>(
|
||||
// line-break
|
||||
QIntC::to_uint(
|
||||
read_bits(this->p, this->bit_offset, this->bits_available, nbits)));
|
||||
QIntC::to_uint(read_bits(this->p, this->bit_offset, this->bits_available, nbits)));
|
||||
}
|
||||
|
||||
void
|
||||
@ -59,8 +57,7 @@ BitStream::skipToNextByte()
|
||||
if (bit_offset != 7) {
|
||||
size_t bits_to_skip = bit_offset + 1;
|
||||
if (bits_available < bits_to_skip) {
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: overflow skipping to next byte in bitstream");
|
||||
throw std::logic_error("INTERNAL ERROR: overflow skipping to next byte in bitstream");
|
||||
}
|
||||
bit_offset = 7;
|
||||
++p;
|
||||
|
@ -5,8 +5,7 @@
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
BufferInputSource::BufferInputSource(
|
||||
std::string const& description, Buffer* buf, bool own_memory) :
|
||||
BufferInputSource::BufferInputSource(std::string const& description, Buffer* buf, bool own_memory) :
|
||||
own_memory(own_memory),
|
||||
description(description),
|
||||
buf(buf),
|
||||
@ -15,8 +14,7 @@ BufferInputSource::BufferInputSource(
|
||||
{
|
||||
}
|
||||
|
||||
BufferInputSource::BufferInputSource(
|
||||
std::string const& description, std::string const& contents) :
|
||||
BufferInputSource::BufferInputSource(std::string const& description, std::string const& contents) :
|
||||
own_memory(true),
|
||||
description(description),
|
||||
buf(new Buffer(contents.length())),
|
||||
@ -100,14 +98,12 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence)
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: invalid argument to BufferInputSource::seek");
|
||||
throw std::logic_error("INTERNAL ERROR: invalid argument to BufferInputSource::seek");
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->cur_offset < 0) {
|
||||
throw std::runtime_error(
|
||||
this->description + ": seek before beginning of buffer");
|
||||
throw std::runtime_error(this->description + ": seek before beginning of buffer");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,13 +44,11 @@ ContentNormalizer::handleToken(QPDFTokenizer::Token const& token)
|
||||
// Replacing string and name tokens in this way normalizes
|
||||
// their representation as this will automatically handle
|
||||
// quoting of unprintable characters, etc.
|
||||
writeToken(
|
||||
QPDFTokenizer::Token(QPDFTokenizer::tt_string, token.getValue()));
|
||||
writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, token.getValue()));
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_name:
|
||||
writeToken(
|
||||
QPDFTokenizer::Token(QPDFTokenizer::tt_name, token.getValue()));
|
||||
writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, token.getValue()));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -59,10 +57,8 @@ ContentNormalizer::handleToken(QPDFTokenizer::Token const& token)
|
||||
}
|
||||
|
||||
value = token.getRawValue();
|
||||
if (((token_type == QPDFTokenizer::tt_string) ||
|
||||
(token_type == QPDFTokenizer::tt_name)) &&
|
||||
((value.find('\r') != std::string::npos) ||
|
||||
(value.find('\n') != std::string::npos))) {
|
||||
if (((token_type == QPDFTokenizer::tt_string) || (token_type == QPDFTokenizer::tt_name)) &&
|
||||
((value.find('\r') != std::string::npos) || (value.find('\n') != std::string::npos))) {
|
||||
write("\n");
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,7 @@ FileInputSource::FileInputSource(char const* filename) :
|
||||
{
|
||||
}
|
||||
|
||||
FileInputSource::FileInputSource(
|
||||
char const* description, FILE* filep, bool close_file) :
|
||||
FileInputSource::FileInputSource(char const* description, FILE* filep, bool close_file) :
|
||||
close_file(close_file),
|
||||
filename(description),
|
||||
file(filep)
|
||||
@ -104,8 +103,8 @@ FileInputSource::seek(qpdf_offset_t offset, int whence)
|
||||
{
|
||||
if (QUtil::seek(this->file, offset, whence) == -1) {
|
||||
QUtil::throw_system_error(
|
||||
std::string("seek to ") + this->filename + ", offset " +
|
||||
std::to_string(offset) + " (" + std::to_string(whence) + ")");
|
||||
std::string("seek to ") + this->filename + ", offset " + std::to_string(offset) + " (" +
|
||||
std::to_string(whence) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,7 @@ InputSource::readLine(size_t max_line_length)
|
||||
}
|
||||
|
||||
bool
|
||||
InputSource::findFirst(
|
||||
char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder)
|
||||
InputSource::findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder)
|
||||
{
|
||||
// Basic approach: search for the first character of start_chars
|
||||
// starting from offset but not going past len (if len != 0). Once
|
||||
@ -64,8 +63,7 @@ InputSource::findFirst(
|
||||
// so that buf[size] is valid memory.
|
||||
size_t size = sizeof(buf) - 1;
|
||||
if ((strlen(start_chars) < 1) || (strlen(start_chars) > size)) {
|
||||
throw std::logic_error(
|
||||
"InputSource::findSource called with"
|
||||
throw std::logic_error("InputSource::findSource called with"
|
||||
" too small or too large of a character sequence");
|
||||
}
|
||||
|
||||
@ -86,13 +84,10 @@ InputSource::findFirst(
|
||||
// If p points to buf[size], since strlen(start_chars) is
|
||||
// always >= 1, this overflow test will be correct for that
|
||||
// case regardless of start_chars.
|
||||
if ((p == nullptr) ||
|
||||
((p + strlen(start_chars)) > (buf + bytes_read))) {
|
||||
if ((p == nullptr) || ((p + strlen(start_chars)) > (buf + bytes_read))) {
|
||||
if (p) {
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"InputSource read next block",
|
||||
((p == buf + bytes_read) ? 0 : 1));
|
||||
"libtests", "InputSource read next block", ((p == buf + bytes_read) ? 0 : 1));
|
||||
buf_offset += (p - buf);
|
||||
}
|
||||
this->seek(buf_offset, SEEK_SET);
|
||||
@ -102,10 +97,7 @@ InputSource::findFirst(
|
||||
// protection against overrun when using string functions.
|
||||
bytes_read = this->read(buf, size);
|
||||
if (bytes_read < strlen(start_chars)) {
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"InputSource find EOF",
|
||||
bytes_read == 0 ? 0 : 1);
|
||||
QTC::TC("libtests", "InputSource find EOF", bytes_read == 0 ? 0 : 1);
|
||||
return false;
|
||||
}
|
||||
memset(buf + bytes_read, '\0', 1 + (size - bytes_read));
|
||||
@ -115,18 +107,14 @@ InputSource::findFirst(
|
||||
// Search for the first character.
|
||||
if ((p = static_cast<char*>(
|
||||
// line-break
|
||||
memchr(
|
||||
p,
|
||||
start_chars[0],
|
||||
bytes_read - QIntC::to_size(p - buf)))) != nullptr) {
|
||||
memchr(p, start_chars[0], bytes_read - QIntC::to_size(p - buf)))) != nullptr) {
|
||||
if (p == buf) {
|
||||
QTC::TC("libtests", "InputSource found match at buf[0]");
|
||||
}
|
||||
// Found first letter.
|
||||
if (len != 0) {
|
||||
// Make sure it's in range.
|
||||
size_t p_relative_offset =
|
||||
QIntC::to_size((p - buf) + (buf_offset - offset));
|
||||
size_t p_relative_offset = QIntC::to_size((p - buf) + (buf_offset - offset));
|
||||
if (p_relative_offset >= len) {
|
||||
// out of range
|
||||
QTC::TC("libtests", "InputSource out of range");
|
||||
@ -151,14 +139,10 @@ InputSource::findFirst(
|
||||
if (finder.check()) {
|
||||
return true;
|
||||
} else {
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"InputSource start_chars matched but not check");
|
||||
QTC::TC("libtests", "InputSource start_chars matched but not check");
|
||||
}
|
||||
} else {
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"InputSource first char matched but not string");
|
||||
QTC::TC("libtests", "InputSource first char matched but not string");
|
||||
}
|
||||
// This occurrence of the first character wasn't a match.
|
||||
// Skip over it and keep searching.
|
||||
@ -172,8 +156,7 @@ InputSource::findFirst(
|
||||
}
|
||||
|
||||
bool
|
||||
InputSource::findLast(
|
||||
char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder)
|
||||
InputSource::findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder)
|
||||
{
|
||||
bool found = false;
|
||||
qpdf_offset_t after_found_offset = 0;
|
||||
|
@ -24,8 +24,7 @@ InsecureRandomDataProvider::random()
|
||||
// Seed the random number generator with something simple, but
|
||||
// just to be interesting, don't use the unmodified current
|
||||
// time. It would be better if this were a more secure seed.
|
||||
auto seed =
|
||||
static_cast<unsigned int>(QUtil::get_current_time() ^ 0xcccc);
|
||||
auto seed = static_cast<unsigned int>(QUtil::get_current_time() ^ 0xcccc);
|
||||
#ifdef HAVE_RANDOM
|
||||
::srandom(seed);
|
||||
#else
|
||||
|
137
libqpdf/JSON.cc
137
libqpdf/JSON.cc
@ -73,8 +73,7 @@ JSON::writeArrayClose(Pipeline* p, bool first, size_t depth)
|
||||
}
|
||||
|
||||
void
|
||||
JSON::writeDictionaryKey(
|
||||
Pipeline* p, bool& first, std::string const& key, size_t depth)
|
||||
JSON::writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth)
|
||||
{
|
||||
writeNext(p, first, depth);
|
||||
*p << std::string("\"") + key + "\": ";
|
||||
@ -82,19 +81,14 @@ JSON::writeDictionaryKey(
|
||||
|
||||
void
|
||||
JSON::writeDictionaryItem(
|
||||
Pipeline* p,
|
||||
bool& first,
|
||||
std::string const& key,
|
||||
JSON const& value,
|
||||
size_t depth)
|
||||
Pipeline* p, bool& first, std::string const& key, JSON const& value, size_t depth)
|
||||
{
|
||||
writeDictionaryKey(p, first, key, depth);
|
||||
value.write(p, depth);
|
||||
}
|
||||
|
||||
void
|
||||
JSON::writeArrayItem(
|
||||
Pipeline* p, bool& first, JSON const& element, size_t depth)
|
||||
JSON::writeArrayItem(Pipeline* p, bool& first, JSON const& element, size_t depth)
|
||||
{
|
||||
writeNext(p, first, depth);
|
||||
element.write(p, depth);
|
||||
@ -283,11 +277,9 @@ JSON
|
||||
JSON::addDictionaryMember(std::string const& key, JSON const& val)
|
||||
{
|
||||
if (auto* obj = dynamic_cast<JSON_dictionary*>(m->value.get())) {
|
||||
return obj->members[encode_string(key)] =
|
||||
val.m->value ? val : makeNull();
|
||||
return obj->members[encode_string(key)] = val.m->value ? val : makeNull();
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
"JSON::addDictionaryMember called on non-dictionary");
|
||||
throw std::runtime_error("JSON::addDictionaryMember called on non-dictionary");
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,8 +288,7 @@ JSON::checkDictionaryKeySeen(std::string const& key)
|
||||
{
|
||||
auto* obj = dynamic_cast<JSON_dictionary*>(m->value.get());
|
||||
if (nullptr == obj) {
|
||||
throw std::logic_error(
|
||||
"JSON::checkDictionaryKey called on non-dictionary");
|
||||
throw std::logic_error("JSON::checkDictionaryKey called on non-dictionary");
|
||||
}
|
||||
if (obj->parsed_keys.count(key)) {
|
||||
return true;
|
||||
@ -421,8 +412,7 @@ JSON::isNull() const
|
||||
}
|
||||
|
||||
bool
|
||||
JSON::forEachDictItem(
|
||||
std::function<void(std::string const& key, JSON value)> fn) const
|
||||
JSON::forEachDictItem(std::function<void(std::string const& key, JSON value)> fn) const
|
||||
{
|
||||
auto v = dynamic_cast<JSON_dictionary const*>(m->value.get());
|
||||
if (v == nullptr) {
|
||||
@ -450,16 +440,13 @@ JSON::forEachArrayItem(std::function<void(JSON value)> fn) const
|
||||
bool
|
||||
JSON::checkSchema(JSON schema, std::list<std::string>& errors)
|
||||
{
|
||||
return checkSchemaInternal(
|
||||
m->value.get(), schema.m->value.get(), 0, errors, "");
|
||||
return checkSchemaInternal(m->value.get(), schema.m->value.get(), 0, errors, "");
|
||||
}
|
||||
|
||||
bool
|
||||
JSON::checkSchema(
|
||||
JSON schema, unsigned long flags, std::list<std::string>& errors)
|
||||
JSON::checkSchema(JSON schema, unsigned long flags, std::list<std::string>& errors)
|
||||
{
|
||||
return checkSchemaInternal(
|
||||
m->value.get(), schema.m->value.get(), flags, errors, "");
|
||||
return checkSchemaInternal(m->value.get(), schema.m->value.get(), flags, errors, "");
|
||||
}
|
||||
|
||||
bool
|
||||
@ -495,8 +482,8 @@ JSON::checkSchemaInternal(
|
||||
auto members = sch_dict->members;
|
||||
std::string key;
|
||||
if ((members.size() == 1) &&
|
||||
((key = members.begin()->first, key.length() > 2) &&
|
||||
(key.at(0) == '<') && (key.at(key.length() - 1) == '>'))) {
|
||||
((key = members.begin()->first, key.length() > 2) && (key.at(0) == '<') &&
|
||||
(key.at(key.length() - 1) == '>'))) {
|
||||
pattern_key = key;
|
||||
}
|
||||
}
|
||||
@ -565,17 +552,12 @@ JSON::checkSchemaInternal(
|
||||
} else {
|
||||
QTC::TC("libtests", "JSON schema array for single item");
|
||||
checkSchemaInternal(
|
||||
this_v,
|
||||
sch_arr->elements.at(0).m->value.get(),
|
||||
flags,
|
||||
errors,
|
||||
prefix);
|
||||
this_v, sch_arr->elements.at(0).m->value.get(), flags, errors, prefix);
|
||||
}
|
||||
} else if (!this_arr || (this_arr->elements.size() != n_elements)) {
|
||||
QTC::TC("libtests", "JSON schema array length mismatch");
|
||||
errors.push_back(
|
||||
err_prefix + " is supposed to be an array of length " +
|
||||
std::to_string(n_elements));
|
||||
err_prefix + " is supposed to be an array of length " + std::to_string(n_elements));
|
||||
return false;
|
||||
} else {
|
||||
// A multi-element array in the schema must correspond to
|
||||
@ -595,8 +577,7 @@ JSON::checkSchemaInternal(
|
||||
}
|
||||
} else if (!sch_str) {
|
||||
QTC::TC("libtests", "JSON schema other type");
|
||||
errors.push_back(
|
||||
err_prefix + " schema value is not dictionary, array, or string");
|
||||
errors.push_back(err_prefix + " schema value is not dictionary, array, or string");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -736,8 +717,7 @@ JSONParser::handle_u_code(
|
||||
" surrogate");
|
||||
}
|
||||
high_offset = 0;
|
||||
codepoint =
|
||||
0x10000U + ((high_surrogate & 0x3FFU) << 10U) + (codepoint & 0x3FF);
|
||||
codepoint = 0x10000U + ((high_surrogate & 0x3FFU) << 10U) + (codepoint & 0x3FF);
|
||||
result += QUtil::toUTF8(codepoint);
|
||||
} else {
|
||||
result += QUtil::toUTF8(codepoint);
|
||||
@ -760,8 +740,8 @@ JSONParser::tokenError()
|
||||
} else if (lex_state == ls_alpha) {
|
||||
QTC::TC("libtests", "JSON parse keyword bad character");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": keyword: unexpected character " + std::string(p, 1));
|
||||
"JSON: offset " + std::to_string(offset) + ": keyword: unexpected character " +
|
||||
std::string(p, 1));
|
||||
} else if (lex_state == ls_string) {
|
||||
QTC::TC("libtests", "JSON parse control char in string");
|
||||
throw std::runtime_error(
|
||||
@ -775,8 +755,7 @@ JSONParser::tokenError()
|
||||
}
|
||||
|
||||
if (*p == '.') {
|
||||
if (lex_state == ls_number || lex_state == ls_number_e ||
|
||||
lex_state == ls_number_e_sign) {
|
||||
if (lex_state == ls_number || lex_state == ls_number_e || lex_state == ls_number_e_sign) {
|
||||
QTC::TC("libtests", "JSON parse point after e");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
@ -790,24 +769,21 @@ JSONParser::tokenError()
|
||||
} else if (*p == 'e' || *p == 'E') {
|
||||
QTC::TC("libtests", "JSON parse duplicate e");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": numeric literal: e already seen");
|
||||
"JSON: offset " + std::to_string(offset) + ": numeric literal: e already seen");
|
||||
} else if ((*p == '+') || (*p == '-')) {
|
||||
QTC::TC("libtests", "JSON parse unexpected sign");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": numeric literal: unexpected sign");
|
||||
"JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected sign");
|
||||
} else if (QUtil::is_space(*p) || strchr("{}[]:,", *p)) {
|
||||
QTC::TC("libtests", "JSON parse incomplete number");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": numeric literal: incomplete number");
|
||||
"JSON: offset " + std::to_string(offset) + ": numeric literal: incomplete number");
|
||||
|
||||
} else {
|
||||
QTC::TC("libtests", "JSON parse numeric bad character");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": numeric literal: unexpected character " + std::string(p, 1));
|
||||
"JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected character " +
|
||||
std::string(p, 1));
|
||||
}
|
||||
throw std::logic_error("JSON::tokenError : unhandled error");
|
||||
}
|
||||
@ -884,8 +860,7 @@ JSONParser::getToken()
|
||||
} else {
|
||||
QTC::TC("libtests", "JSON parse null character");
|
||||
throw std::runtime_error(
|
||||
"JSON: control or null character at offset " +
|
||||
std::to_string(offset));
|
||||
"JSON: control or null character at offset " + std::to_string(offset));
|
||||
}
|
||||
} else if (*p == ',') {
|
||||
if (lex_state == ls_top) {
|
||||
@ -968,8 +943,8 @@ JSONParser::getToken()
|
||||
} else {
|
||||
QTC::TC("libtests", "JSON parse bad character");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": unexpected character " + std::string(p, 1));
|
||||
"JSON: offset " + std::to_string(offset) + ": unexpected character " +
|
||||
std::string(p, 1));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -994,8 +969,7 @@ JSONParser::getToken()
|
||||
} else {
|
||||
QTC::TC("libtests", "JSON parse leading zero");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": number with leading zero");
|
||||
"JSON: offset " + std::to_string(offset) + ": number with leading zero");
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1127,20 +1101,14 @@ JSONParser::getToken()
|
||||
tokenError();
|
||||
}
|
||||
if (++u_count == 4) {
|
||||
handle_u_code(
|
||||
u_value,
|
||||
offset - 5,
|
||||
high_surrogate,
|
||||
high_offset,
|
||||
token);
|
||||
handle_u_code(u_value, offset - 5, high_surrogate, high_offset, token);
|
||||
lex_state = ls_string;
|
||||
}
|
||||
ignore();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error(
|
||||
"JSONParser::getToken : trying to handle delimiter state");
|
||||
throw std::logic_error("JSONParser::getToken : trying to handle delimiter state");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1205,19 +1173,16 @@ JSONParser::handleToken()
|
||||
if (parser_state != ps_dict_after_key) {
|
||||
QTC::TC("libtests", "JSON parse unexpected :");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": unexpected colon");
|
||||
"JSON: offset " + std::to_string(offset) + ": unexpected colon");
|
||||
}
|
||||
parser_state = ps_dict_after_colon;
|
||||
return;
|
||||
|
||||
case ls_comma:
|
||||
if (!((parser_state == ps_dict_after_item) ||
|
||||
(parser_state == ps_array_after_item))) {
|
||||
if (!((parser_state == ps_dict_after_item) || (parser_state == ps_array_after_item))) {
|
||||
QTC::TC("libtests", "JSON parse unexpected ,");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": unexpected comma");
|
||||
"JSON: offset " + std::to_string(offset) + ": unexpected comma");
|
||||
}
|
||||
if (parser_state == ps_dict_after_item) {
|
||||
parser_state = ps_dict_after_comma;
|
||||
@ -1230,12 +1195,10 @@ JSONParser::handleToken()
|
||||
return;
|
||||
|
||||
case ls_end_array:
|
||||
if (!(parser_state == ps_array_begin ||
|
||||
parser_state == ps_array_after_item)) {
|
||||
if (!(parser_state == ps_array_begin || parser_state == ps_array_after_item)) {
|
||||
QTC::TC("libtests", "JSON parse unexpected ]");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": unexpected array end delimiter");
|
||||
"JSON: offset " + std::to_string(offset) + ": unexpected array end delimiter");
|
||||
}
|
||||
parser_state = stack.back().state;
|
||||
tos.setEnd(offset);
|
||||
@ -1248,12 +1211,10 @@ JSONParser::handleToken()
|
||||
return;
|
||||
|
||||
case ls_end_dict:
|
||||
if (!((parser_state == ps_dict_begin) ||
|
||||
(parser_state == ps_dict_after_item))) {
|
||||
if (!((parser_state == ps_dict_begin) || (parser_state == ps_dict_after_item))) {
|
||||
QTC::TC("libtests", "JSON parse unexpected }");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": unexpected dictionary end delimiter");
|
||||
"JSON: offset " + std::to_string(offset) + ": unexpected dictionary end delimiter");
|
||||
}
|
||||
parser_state = stack.back().state;
|
||||
tos.setEnd(offset);
|
||||
@ -1279,14 +1240,12 @@ JSONParser::handleToken()
|
||||
} else {
|
||||
QTC::TC("libtests", "JSON parse invalid keyword");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": invalid keyword " + token);
|
||||
"JSON: offset " + std::to_string(offset) + ": invalid keyword " + token);
|
||||
}
|
||||
break;
|
||||
|
||||
case ls_string:
|
||||
if (parser_state == ps_dict_begin ||
|
||||
parser_state == ps_dict_after_comma) {
|
||||
if (parser_state == ps_dict_begin || parser_state == ps_dict_after_comma) {
|
||||
dict_key = token;
|
||||
dict_key_offset = token_start;
|
||||
parser_state = ps_dict_after_key;
|
||||
@ -1297,8 +1256,7 @@ JSONParser::handleToken()
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error(
|
||||
"JSONParser::handleToken : non-terminal lexer state encountered");
|
||||
throw std::logic_error("JSONParser::handleToken : non-terminal lexer state encountered");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1310,16 +1268,14 @@ JSONParser::handleToken()
|
||||
case ps_dict_after_comma:
|
||||
QTC::TC("libtests", "JSON parse string as dict key");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": expect string as dictionary key");
|
||||
"JSON: offset " + std::to_string(offset) + ": expect string as dictionary key");
|
||||
break;
|
||||
|
||||
case ps_dict_after_colon:
|
||||
if (tos.checkDictionaryKeySeen(dict_key)) {
|
||||
QTC::TC("libtests", "JSON parse duplicate key");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(dict_key_offset) +
|
||||
": duplicated dictionary key");
|
||||
"JSON: offset " + std::to_string(dict_key_offset) + ": duplicated dictionary key");
|
||||
}
|
||||
if (!reactor || !reactor->dictionaryItem(dict_key, item)) {
|
||||
tos.addDictionaryMember(dict_key, item);
|
||||
@ -1346,8 +1302,7 @@ JSONParser::handleToken()
|
||||
|
||||
case ps_dict_after_key:
|
||||
QTC::TC("libtests", "JSON parse expected colon");
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) + ": expected ':'");
|
||||
throw std::runtime_error("JSON: offset " + std::to_string(offset) + ": expected ':'");
|
||||
break;
|
||||
|
||||
case ps_dict_after_item:
|
||||
@ -1363,8 +1318,7 @@ JSONParser::handleToken()
|
||||
break;
|
||||
|
||||
case ps_done:
|
||||
throw std::logic_error(
|
||||
"JSONParser::handleToken: unexpected parser state");
|
||||
throw std::logic_error("JSONParser::handleToken: unexpected parser state");
|
||||
}
|
||||
|
||||
if (item.isDictionary() || item.isArray()) {
|
||||
@ -1387,8 +1341,7 @@ JSONParser::handleToken()
|
||||
|
||||
if (stack.size() > 500) {
|
||||
throw std::runtime_error(
|
||||
"JSON: offset " + std::to_string(offset) +
|
||||
": maximum object depth exceeded");
|
||||
"JSON: offset " + std::to_string(offset) + ": maximum object depth exceeded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,7 @@ JSONHandler::addDictHandlers(json_handler_t start_fn, void_handler_t end_fn)
|
||||
}
|
||||
|
||||
void
|
||||
JSONHandler::addDictKeyHandler(
|
||||
std::string const& key, std::shared_ptr<JSONHandler> dkh)
|
||||
JSONHandler::addDictKeyHandler(std::string const& key, std::shared_ptr<JSONHandler> dkh)
|
||||
{
|
||||
m->h.dict_handlers[key] = dkh;
|
||||
}
|
||||
@ -67,9 +66,7 @@ JSONHandler::addFallbackDictHandler(std::shared_ptr<JSONHandler> fdh)
|
||||
|
||||
void
|
||||
JSONHandler::addArrayHandlers(
|
||||
json_handler_t start_fn,
|
||||
void_handler_t end_fn,
|
||||
std::shared_ptr<JSONHandler> ah)
|
||||
json_handler_t start_fn, void_handler_t end_fn, std::shared_ptr<JSONHandler> ah)
|
||||
{
|
||||
m->h.array_start_handler = start_fn;
|
||||
m->h.array_end_handler = end_fn;
|
||||
@ -108,17 +105,14 @@ JSONHandler::handle(std::string const& path, JSON j)
|
||||
if (path_base != ".") {
|
||||
path_base += ".";
|
||||
}
|
||||
j.forEachDictItem(
|
||||
[&path, &path_base, this](std::string const& k, JSON v) {
|
||||
j.forEachDictItem([&path, &path_base, this](std::string const& k, JSON v) {
|
||||
auto i = m->h.dict_handlers.find(k);
|
||||
if (i == m->h.dict_handlers.end()) {
|
||||
if (m->h.fallback_dict_handler.get()) {
|
||||
m->h.fallback_dict_handler->handle(path_base + k, v);
|
||||
} else {
|
||||
QTC::TC("libtests", "JSONHandler unexpected key");
|
||||
usage(
|
||||
"JSON handler found unexpected key " + k +
|
||||
" in object at " + path);
|
||||
usage("JSON handler found unexpected key " + k + " in object at " + path);
|
||||
}
|
||||
} else {
|
||||
i->second->handle(path_base + k, v);
|
||||
@ -131,8 +125,7 @@ JSONHandler::handle(std::string const& path, JSON j)
|
||||
m->h.array_start_handler(path, j);
|
||||
size_t i = 0;
|
||||
j.forEachArrayItem([&i, &path, this](JSON v) {
|
||||
m->h.array_item_handler->handle(
|
||||
path + "[" + std::to_string(i) + "]", v);
|
||||
m->h.array_item_handler->handle(path + "[" + std::to_string(i) + "]", v);
|
||||
++i;
|
||||
});
|
||||
m->h.array_end_handler(path);
|
||||
|
@ -81,8 +81,7 @@ MD5::encodeFile(char const* filename, qpdf_offset_t up_to_offset)
|
||||
// Assume, perhaps incorrectly, that errno was set by the
|
||||
// underlying call to read....
|
||||
(void)fclose(file);
|
||||
QUtil::throw_system_error(
|
||||
std::string("MD5: read error on ") + filename);
|
||||
QUtil::throw_system_error(std::string("MD5: read error on ") + filename);
|
||||
}
|
||||
(void)fclose(file);
|
||||
|
||||
@ -115,8 +114,7 @@ MD5::unparse()
|
||||
this->crypto->MD5_finalize();
|
||||
Digest digest_val;
|
||||
digest(digest_val);
|
||||
return QUtil::hex_encode(
|
||||
std::string(reinterpret_cast<char*>(digest_val), 16));
|
||||
return QUtil::hex_encode(std::string(reinterpret_cast<char*>(digest_val), 16));
|
||||
}
|
||||
|
||||
std::string
|
||||
@ -143,10 +141,7 @@ MD5::checkDataChecksum(char const* const checksum, char const* buf, size_t len)
|
||||
}
|
||||
|
||||
bool
|
||||
MD5::checkFileChecksum(
|
||||
char const* const checksum,
|
||||
char const* filename,
|
||||
qpdf_offset_t up_to_offset)
|
||||
MD5::checkFileChecksum(char const* const checksum, char const* filename, qpdf_offset_t up_to_offset)
|
||||
{
|
||||
bool result = false;
|
||||
try {
|
||||
|
@ -24,8 +24,7 @@ warn(QPDF& qpdf, QPDFObjectHandle& node, std::string const& msg)
|
||||
static void
|
||||
error(QPDF& qpdf, QPDFObjectHandle& node, std::string const& msg)
|
||||
{
|
||||
throw QPDFExc(
|
||||
qpdf_e_damaged_pdf, qpdf.getFilename(), get_description(node), 0, msg);
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, qpdf.getFilename(), get_description(node), 0, msg);
|
||||
}
|
||||
|
||||
NNTreeIterator::NNTreeIterator(NNTreeImpl& impl) :
|
||||
@ -76,8 +75,7 @@ NNTreeIterator::updateIValue(bool allow_invalid)
|
||||
}
|
||||
}
|
||||
|
||||
NNTreeIterator::PathElement::PathElement(
|
||||
QPDFObjectHandle const& node, int kid_number) :
|
||||
NNTreeIterator::PathElement::PathElement(QPDFObjectHandle const& node, int kid_number) :
|
||||
node(node),
|
||||
kid_number(kid_number)
|
||||
{
|
||||
@ -94,16 +92,14 @@ NNTreeIterator::getNextKid(PathElement& pe, bool backward)
|
||||
if ((pe.kid_number >= 0) && (pe.kid_number < kids.getArrayNItems())) {
|
||||
result = kids.getArrayItem(pe.kid_number);
|
||||
if (result.isDictionary() &&
|
||||
(result.hasKey("/Kids") ||
|
||||
result.hasKey(impl.details.itemsKey()))) {
|
||||
(result.hasKey("/Kids") || result.hasKey(impl.details.itemsKey()))) {
|
||||
found = true;
|
||||
} else {
|
||||
QTC::TC("qpdf", "NNTree skip invalid kid");
|
||||
warn(
|
||||
impl.qpdf,
|
||||
pe.node,
|
||||
("skipping over invalid kid at index " +
|
||||
std::to_string(pe.kid_number)));
|
||||
("skipping over invalid kid at index " + std::to_string(pe.kid_number)));
|
||||
}
|
||||
} else {
|
||||
result = QPDFObjectHandle::newNull();
|
||||
@ -131,8 +127,7 @@ NNTreeIterator::increment(bool backward)
|
||||
while (valid() && (!found_valid_key)) {
|
||||
this->item_number += backward ? -2 : 2;
|
||||
auto items = this->node.getKey(impl.details.itemsKey());
|
||||
if ((this->item_number < 0) ||
|
||||
(this->item_number >= items.getArrayNItems())) {
|
||||
if ((this->item_number < 0) || (this->item_number >= items.getArrayNItems())) {
|
||||
bool found = false;
|
||||
setItemNumber(QPDFObjectHandle(), -1);
|
||||
while (!(found || this->path.empty())) {
|
||||
@ -149,18 +144,13 @@ NNTreeIterator::increment(bool backward)
|
||||
items = this->node.getKey(impl.details.itemsKey());
|
||||
if (this->item_number + 1 >= items.getArrayNItems()) {
|
||||
QTC::TC("qpdf", "NNTree skip item at end of short items");
|
||||
warn(
|
||||
impl.qpdf,
|
||||
this->node,
|
||||
"items array doesn't have enough elements");
|
||||
} else if (!impl.details.keyValid(
|
||||
items.getArrayItem(this->item_number))) {
|
||||
warn(impl.qpdf, this->node, "items array doesn't have enough elements");
|
||||
} else if (!impl.details.keyValid(items.getArrayItem(this->item_number))) {
|
||||
QTC::TC("qpdf", "NNTree skip invalid key");
|
||||
warn(
|
||||
impl.qpdf,
|
||||
this->node,
|
||||
("item " + std::to_string(this->item_number) +
|
||||
" has the wrong type"));
|
||||
("item " + std::to_string(this->item_number) + " has the wrong type"));
|
||||
} else {
|
||||
found_valid_key = true;
|
||||
}
|
||||
@ -169,8 +159,7 @@ NNTreeIterator::increment(bool backward)
|
||||
}
|
||||
|
||||
void
|
||||
NNTreeIterator::resetLimits(
|
||||
QPDFObjectHandle node, std::list<PathElement>::iterator parent)
|
||||
NNTreeIterator::resetLimits(QPDFObjectHandle node, std::list<PathElement>::iterator parent)
|
||||
{
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
@ -197,10 +186,8 @@ NNTreeIterator::resetLimits(
|
||||
if (first_kid.isDictionary() && last_kid.isDictionary()) {
|
||||
auto first_limits = first_kid.getKey("/Limits");
|
||||
auto last_limits = last_kid.getKey("/Limits");
|
||||
if (first_limits.isArray() &&
|
||||
(first_limits.getArrayNItems() >= 2) &&
|
||||
last_limits.isArray() &&
|
||||
(last_limits.getArrayNItems() >= 2)) {
|
||||
if (first_limits.isArray() && (first_limits.getArrayNItems() >= 2) &&
|
||||
last_limits.isArray() && (last_limits.getArrayNItems() >= 2)) {
|
||||
first = first_limits.getArrayItem(0);
|
||||
last = last_limits.getArrayItem(1);
|
||||
}
|
||||
@ -214,8 +201,7 @@ NNTreeIterator::resetLimits(
|
||||
if (olimits.isArray() && (olimits.getArrayNItems() == 2)) {
|
||||
auto ofirst = olimits.getArrayItem(0);
|
||||
auto olast = olimits.getArrayItem(1);
|
||||
if (impl.details.keyValid(ofirst) &&
|
||||
impl.details.keyValid(olast) &&
|
||||
if (impl.details.keyValid(ofirst) && impl.details.keyValid(olast) &&
|
||||
(impl.details.compareKeys(first, ofirst) == 0) &&
|
||||
(impl.details.compareKeys(last, olast) == 0)) {
|
||||
QTC::TC("qpdf", "NNTree limits didn't change");
|
||||
@ -240,8 +226,7 @@ NNTreeIterator::resetLimits(
|
||||
}
|
||||
|
||||
void
|
||||
NNTreeIterator::split(
|
||||
QPDFObjectHandle to_split, std::list<PathElement>::iterator parent)
|
||||
NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterator parent)
|
||||
{
|
||||
// Split some node along the path to the item pointed to by this
|
||||
// iterator, and adjust the iterator so it points to the same
|
||||
@ -272,8 +257,7 @@ NNTreeIterator::split(
|
||||
// item_number: 0
|
||||
|
||||
if (!valid()) {
|
||||
throw std::logic_error(
|
||||
"NNTreeIterator::split called an invalid iterator");
|
||||
throw std::logic_error("NNTreeIterator::split called an invalid iterator");
|
||||
}
|
||||
|
||||
// Find the array we actually need to split, which is either this
|
||||
@ -335,8 +319,7 @@ NNTreeIterator::split(
|
||||
// non-root case so remaining logic can handle them in the
|
||||
// same way.
|
||||
|
||||
auto first_node =
|
||||
impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary());
|
||||
auto first_node = impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary());
|
||||
first_node.replaceKey(key, first_half);
|
||||
QPDFObjectHandle new_kids = QPDFObjectHandle::newArray();
|
||||
new_kids.appendItem(first_node);
|
||||
@ -371,8 +354,7 @@ NNTreeIterator::split(
|
||||
resetLimits(to_split, parent);
|
||||
|
||||
// Create a new node to contain the second half
|
||||
QPDFObjectHandle second_node =
|
||||
impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary());
|
||||
QPDFObjectHandle second_node = impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary());
|
||||
second_node.replaceKey(key, second_half);
|
||||
resetLimits(second_node, parent);
|
||||
|
||||
@ -457,10 +439,7 @@ NNTreeIterator::remove()
|
||||
auto items = this->node.getKey(impl.details.itemsKey());
|
||||
int nitems = items.getArrayNItems();
|
||||
if (this->item_number + 2 > nitems) {
|
||||
error(
|
||||
impl.qpdf,
|
||||
this->node,
|
||||
"found short items array while removing an item");
|
||||
error(impl.qpdf, this->node, "found short items array while removing an item");
|
||||
}
|
||||
|
||||
items.eraseItem(this->item_number);
|
||||
@ -491,8 +470,7 @@ NNTreeIterator::remove()
|
||||
} else {
|
||||
// We already checked to ensure this condition would not
|
||||
// happen.
|
||||
throw std::logic_error(
|
||||
"NNTreeIterator::remove: item_number > nitems after erase");
|
||||
throw std::logic_error("NNTreeIterator::remove: item_number > nitems after erase");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -549,8 +527,7 @@ NNTreeIterator::remove()
|
||||
// empty items array.
|
||||
QTC::TC("qpdf", "NNTree non-flat tree is empty after remove");
|
||||
element->node.removeKey("/Kids");
|
||||
element->node.replaceKey(
|
||||
impl.details.itemsKey(), QPDFObjectHandle::newArray());
|
||||
element->node.replaceKey(impl.details.itemsKey(), QPDFObjectHandle::newArray());
|
||||
this->path.clear();
|
||||
setItemNumber(impl.oh, -1);
|
||||
done = true;
|
||||
@ -645,20 +622,14 @@ NNTreeIterator::deepen(QPDFObjectHandle node, bool first, bool allow_empty)
|
||||
while (!failed) {
|
||||
if (!seen.add(node)) {
|
||||
QTC::TC("qpdf", "NNTree deepen: loop");
|
||||
warn(
|
||||
impl.qpdf,
|
||||
node,
|
||||
"loop detected while traversing name/number tree");
|
||||
warn(impl.qpdf, node, "loop detected while traversing name/number tree");
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!node.isDictionary()) {
|
||||
QTC::TC("qpdf", "NNTree node is not a dictionary");
|
||||
warn(
|
||||
impl.qpdf,
|
||||
node,
|
||||
"non-dictionary node while traversing name/number tree");
|
||||
warn(impl.qpdf, node, "non-dictionary node while traversing name/number tree");
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
@ -703,8 +674,8 @@ NNTreeIterator::deepen(QPDFObjectHandle node, bool first, bool allow_empty)
|
||||
warn(
|
||||
impl.qpdf,
|
||||
node,
|
||||
("name/number tree node has neither non-empty " +
|
||||
impl.details.itemsKey() + " nor /Kids"));
|
||||
("name/number tree node has neither non-empty " + impl.details.itemsKey() +
|
||||
" nor /Kids"));
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
@ -717,10 +688,7 @@ NNTreeIterator::deepen(QPDFObjectHandle node, bool first, bool allow_empty)
|
||||
}
|
||||
|
||||
NNTreeImpl::NNTreeImpl(
|
||||
NNTreeDetails const& details,
|
||||
QPDF& qpdf,
|
||||
QPDFObjectHandle& oh,
|
||||
bool auto_repair) :
|
||||
NNTreeDetails const& details, QPDF& qpdf, QPDFObjectHandle& oh, bool auto_repair) :
|
||||
details(details),
|
||||
qpdf(qpdf),
|
||||
split_threshold(32),
|
||||
@ -763,8 +731,7 @@ NNTreeImpl::withinLimits(QPDFObjectHandle key, QPDFObjectHandle node)
|
||||
int result = 0;
|
||||
auto limits = node.getKey("/Limits");
|
||||
if (limits.isArray() && (limits.getArrayNItems() >= 2) &&
|
||||
details.keyValid(limits.getArrayItem(0)) &&
|
||||
details.keyValid(limits.getArrayItem(1))) {
|
||||
details.keyValid(limits.getArrayItem(0)) && details.keyValid(limits.getArrayItem(1))) {
|
||||
if (details.compareKeys(key, limits.getArrayItem(0)) < 0) {
|
||||
result = -1;
|
||||
} else if (details.compareKeys(key, limits.getArrayItem(1)) > 0) {
|
||||
@ -783,8 +750,7 @@ NNTreeImpl::binarySearch(
|
||||
QPDFObjectHandle items,
|
||||
int num_items,
|
||||
bool return_prev_if_not_found,
|
||||
int (NNTreeImpl::*compare)(
|
||||
QPDFObjectHandle& key, QPDFObjectHandle& arr, int item))
|
||||
int (NNTreeImpl::*compare)(QPDFObjectHandle& key, QPDFObjectHandle& arr, int item))
|
||||
{
|
||||
int max_idx = 1;
|
||||
while (max_idx < num_items) {
|
||||
@ -838,8 +804,7 @@ NNTreeImpl::binarySearch(
|
||||
}
|
||||
|
||||
int
|
||||
NNTreeImpl::compareKeyItem(
|
||||
QPDFObjectHandle& key, QPDFObjectHandle& items, int idx)
|
||||
NNTreeImpl::compareKeyItem(QPDFObjectHandle& key, QPDFObjectHandle& items, int idx)
|
||||
{
|
||||
if (!((items.isArray() && (items.getArrayNItems() > (2 * idx)) &&
|
||||
details.keyValid(items.getArrayItem(2 * idx))))) {
|
||||
@ -847,15 +812,13 @@ NNTreeImpl::compareKeyItem(
|
||||
error(
|
||||
qpdf,
|
||||
this->oh,
|
||||
("item at index " + std::to_string(2 * idx) +
|
||||
" is not the right type"));
|
||||
("item at index " + std::to_string(2 * idx) + " is not the right type"));
|
||||
}
|
||||
return details.compareKeys(key, items.getArrayItem(2 * idx));
|
||||
}
|
||||
|
||||
int
|
||||
NNTreeImpl::compareKeyKid(
|
||||
QPDFObjectHandle& key, QPDFObjectHandle& kids, int idx)
|
||||
NNTreeImpl::compareKeyKid(QPDFObjectHandle& key, QPDFObjectHandle& kids, int idx)
|
||||
{
|
||||
if (!(kids.isArray() && (idx < kids.getArrayNItems()) &&
|
||||
kids.getArrayItem(idx).isDictionary())) {
|
||||
@ -875,8 +838,7 @@ NNTreeImpl::repair()
|
||||
repl.insert(i.first, i.second);
|
||||
}
|
||||
this->oh.replaceKey("/Kids", new_node.getKey("/Kids"));
|
||||
this->oh.replaceKey(
|
||||
details.itemsKey(), new_node.getKey(details.itemsKey()));
|
||||
this->oh.replaceKey(details.itemsKey(), new_node.getKey(details.itemsKey()));
|
||||
}
|
||||
|
||||
NNTreeImpl::iterator
|
||||
@ -887,10 +849,7 @@ NNTreeImpl::find(QPDFObjectHandle key, bool return_prev_if_not_found)
|
||||
} catch (QPDFExc& e) {
|
||||
if (this->auto_repair) {
|
||||
QTC::TC("qpdf", "NNTree repair");
|
||||
warn(
|
||||
qpdf,
|
||||
this->oh,
|
||||
std::string("attempting to repair after error: ") + e.what());
|
||||
warn(qpdf, this->oh, std::string("attempting to repair after error: ") + e.what());
|
||||
repair();
|
||||
return findInternal(key, return_prev_if_not_found);
|
||||
} else {
|
||||
@ -939,18 +898,13 @@ NNTreeImpl::findInternal(QPDFObjectHandle key, bool return_prev_if_not_found)
|
||||
int nitems = items.isArray() ? items.getArrayNItems() : 0;
|
||||
if (nitems > 0) {
|
||||
int idx = binarySearch(
|
||||
key,
|
||||
items,
|
||||
nitems / 2,
|
||||
return_prev_if_not_found,
|
||||
&NNTreeImpl::compareKeyItem);
|
||||
key, items, nitems / 2, return_prev_if_not_found, &NNTreeImpl::compareKeyItem);
|
||||
if (idx >= 0) {
|
||||
result.setItemNumber(node, 2 * idx);
|
||||
}
|
||||
break;
|
||||
} else if (nkids > 0) {
|
||||
int idx = binarySearch(
|
||||
key, kids, nkids, true, &NNTreeImpl::compareKeyKid);
|
||||
int idx = binarySearch(key, kids, nkids, true, &NNTreeImpl::compareKeyKid);
|
||||
if (idx == -1) {
|
||||
QTC::TC("qpdf", "NNTree -1 in binary search");
|
||||
error(
|
||||
|
@ -10,11 +10,9 @@ OffsetInputSource::OffsetInputSource(
|
||||
global_offset(global_offset)
|
||||
{
|
||||
if (global_offset < 0) {
|
||||
throw std::logic_error(
|
||||
"OffsetInputSource constructed with negative offset");
|
||||
throw std::logic_error("OffsetInputSource constructed with negative offset");
|
||||
}
|
||||
this->max_safe_offset =
|
||||
std::numeric_limits<qpdf_offset_t>::max() - global_offset;
|
||||
this->max_safe_offset = std::numeric_limits<qpdf_offset_t>::max() - global_offset;
|
||||
}
|
||||
|
||||
qpdf_offset_t
|
||||
@ -51,8 +49,7 @@ OffsetInputSource::seek(qpdf_offset_t offset, int whence)
|
||||
this->proxied->seek(offset, whence);
|
||||
}
|
||||
if (tell() < 0) {
|
||||
throw std::runtime_error(
|
||||
"offset input source: seek before beginning of file");
|
||||
throw std::runtime_error("offset input source: seek before beginning of file");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,7 @@ PDFVersion::PDFVersion() :
|
||||
{
|
||||
}
|
||||
|
||||
PDFVersion::PDFVersion(
|
||||
int major_version, int minor_version, int extension_level) :
|
||||
PDFVersion::PDFVersion(int major_version, int minor_version, int extension_level) :
|
||||
major_version(major_version),
|
||||
minor_version(minor_version),
|
||||
extension_level(extension_level)
|
||||
@ -31,8 +30,7 @@ bool
|
||||
PDFVersion::operator==(PDFVersion const& rhs) const
|
||||
{
|
||||
return (
|
||||
(this->major_version == rhs.major_version) &&
|
||||
(this->minor_version == rhs.minor_version) &&
|
||||
(this->major_version == rhs.major_version) && (this->minor_version == rhs.minor_version) &&
|
||||
(this->extension_level == rhs.extension_level));
|
||||
}
|
||||
|
||||
@ -48,8 +46,7 @@ void
|
||||
PDFVersion::getVersion(std::string& version, int& extension_level) const
|
||||
{
|
||||
extension_level = this->extension_level;
|
||||
version = std::to_string(this->major_version) + "." +
|
||||
std::to_string(this->minor_version);
|
||||
version = std::to_string(this->major_version) + "." + std::to_string(this->minor_version);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -14,8 +14,7 @@ Pipeline::getNext(bool allow_null)
|
||||
{
|
||||
if ((this->next == nullptr) && (!allow_null)) {
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pipeline::getNext() called on pipeline with no next");
|
||||
this->identifier + ": Pipeline::getNext() called on pipeline with no next");
|
||||
}
|
||||
return this->next;
|
||||
}
|
||||
|
@ -117,8 +117,7 @@ Pl_AES_PDF::finish()
|
||||
throw std::logic_error("buffer overflow in AES encryption"
|
||||
" pipeline");
|
||||
}
|
||||
std::memset(
|
||||
this->inbuf + this->offset, 0, this->buf_size - this->offset);
|
||||
std::memset(this->inbuf + this->offset, 0, this->buf_size - this->offset);
|
||||
this->offset = this->buf_size;
|
||||
}
|
||||
flush(!this->disable_padding);
|
||||
@ -149,8 +148,7 @@ void
|
||||
Pl_AES_PDF::flush(bool strip_padding)
|
||||
{
|
||||
if (this->offset != this->buf_size) {
|
||||
throw std::logic_error(
|
||||
"AES pipeline: flush called when buffer was not full");
|
||||
throw std::logic_error("AES pipeline: flush called when buffer was not full");
|
||||
}
|
||||
|
||||
if (first) {
|
||||
@ -177,11 +175,7 @@ Pl_AES_PDF::flush(bool strip_padding)
|
||||
}
|
||||
}
|
||||
this->crypto->rijndael_init(
|
||||
encrypt,
|
||||
this->key.get(),
|
||||
key_bytes,
|
||||
this->cbc_mode,
|
||||
this->cbc_block);
|
||||
encrypt, this->key.get(), key_bytes, this->cbc_mode, this->cbc_block);
|
||||
if (return_after_init) {
|
||||
return;
|
||||
}
|
||||
|
@ -26,8 +26,7 @@ Pl_ASCII85Decoder::write(unsigned char const* buf, size_t len)
|
||||
flush();
|
||||
eod = 2;
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
"broken end-of-data sequence in base 85 data");
|
||||
throw std::runtime_error("broken end-of-data sequence in base 85 data");
|
||||
}
|
||||
} else {
|
||||
switch (buf[i]) {
|
||||
@ -47,8 +46,7 @@ Pl_ASCII85Decoder::write(unsigned char const* buf, size_t len)
|
||||
|
||||
case 'z':
|
||||
if (pos != 0) {
|
||||
throw std::runtime_error(
|
||||
"unexpected z during base 85 decode");
|
||||
throw std::runtime_error("unexpected z during base 85 decode");
|
||||
} else {
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
|
||||
unsigned char zeroes[4];
|
||||
@ -59,8 +57,7 @@ Pl_ASCII85Decoder::write(unsigned char const* buf, size_t len)
|
||||
|
||||
default:
|
||||
if ((buf[i] < 33) || (buf[i] > 117)) {
|
||||
throw std::runtime_error(
|
||||
"character out of range during base 85 decode");
|
||||
throw std::runtime_error("character out of range during base 85 decode");
|
||||
} else {
|
||||
this->inbuf[this->pos++] = buf[i];
|
||||
if (pos == 5) {
|
||||
@ -93,10 +90,7 @@ Pl_ASCII85Decoder::flush()
|
||||
lval >>= 8;
|
||||
}
|
||||
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"Pl_ASCII85Decoder partial flush",
|
||||
(this->pos == 5) ? 0 : 1);
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder partial flush", (this->pos == 5) ? 0 : 1);
|
||||
// Reset before calling getNext()->write in case that throws an
|
||||
// exception.
|
||||
auto t = this->pos - 1;
|
||||
|
@ -78,10 +78,7 @@ Pl_ASCIIHexDecoder::flush()
|
||||
}
|
||||
auto ch = static_cast<unsigned char>((b[0] << 4) + b[1]);
|
||||
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"Pl_ASCIIHexDecoder partial flush",
|
||||
(this->pos == 2) ? 0 : 1);
|
||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush", (this->pos == 2) ? 0 : 1);
|
||||
// Reset before calling getNext()->write in case that throws an
|
||||
// exception.
|
||||
this->pos = 0;
|
||||
|
@ -91,8 +91,7 @@ void
|
||||
Pl_Base64::flush_decode()
|
||||
{
|
||||
if (this->end_of_data) {
|
||||
throw std::runtime_error(
|
||||
getIdentifier() + ": base64 decode: data follows pad characters");
|
||||
throw std::runtime_error(getIdentifier() + ": base64 decode: data follows pad characters");
|
||||
}
|
||||
int pad = 0;
|
||||
int shift = 18;
|
||||
@ -110,14 +109,12 @@ Pl_Base64::flush_decode()
|
||||
v = 62;
|
||||
} else if ((ch == '/') || (ch == '_')) {
|
||||
v = 63;
|
||||
} else if (
|
||||
(ch == '=') && ((i == 3) || ((i == 2) && (this->buf[3] == '=')))) {
|
||||
} else if ((ch == '=') && ((i == 3) || ((i == 2) && (this->buf[3] == '=')))) {
|
||||
++pad;
|
||||
this->end_of_data = true;
|
||||
v = 0;
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
getIdentifier() + ": base64 decode: invalid input");
|
||||
throw std::runtime_error(getIdentifier() + ": base64 decode: invalid input");
|
||||
}
|
||||
outval |= v << shift;
|
||||
shift -= 6;
|
||||
|
@ -64,8 +64,7 @@ void
|
||||
Pl_Buffer::getMallocBuffer(unsigned char** buf, size_t* len)
|
||||
{
|
||||
if (!m->ready) {
|
||||
throw std::logic_error(
|
||||
"Pl_Buffer::getMallocBuffer() called when not ready");
|
||||
throw std::logic_error("Pl_Buffer::getMallocBuffer() called when not ready");
|
||||
}
|
||||
auto size = m->data.length();
|
||||
*len = size;
|
||||
|
@ -182,15 +182,12 @@ term_pipeline_destination(j_compress_ptr cinfo)
|
||||
}
|
||||
|
||||
static void
|
||||
jpeg_pipeline_dest(
|
||||
j_compress_ptr cinfo, unsigned char* outbuffer, size_t size, Pipeline* next)
|
||||
jpeg_pipeline_dest(j_compress_ptr cinfo, unsigned char* outbuffer, size_t size, Pipeline* next)
|
||||
{
|
||||
cinfo->dest = static_cast<struct jpeg_destination_mgr*>(
|
||||
// line-break
|
||||
(*cinfo->mem->alloc_small)(
|
||||
reinterpret_cast<j_common_ptr>(cinfo),
|
||||
JPOOL_PERMANENT,
|
||||
sizeof(dct_pipeline_dest)));
|
||||
reinterpret_cast<j_common_ptr>(cinfo), JPOOL_PERMANENT, sizeof(dct_pipeline_dest)));
|
||||
auto* dest = reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
||||
dest->pub.init_destination = init_pipeline_destination;
|
||||
dest->pub.empty_output_buffer = empty_pipeline_output_buffer;
|
||||
@ -243,9 +240,7 @@ jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer)
|
||||
cinfo->src = reinterpret_cast<jpeg_source_mgr*>(
|
||||
// line-break
|
||||
(*cinfo->mem->alloc_small)(
|
||||
reinterpret_cast<j_common_ptr>(cinfo),
|
||||
JPOOL_PERMANENT,
|
||||
sizeof(jpeg_source_mgr)));
|
||||
reinterpret_cast<j_common_ptr>(cinfo), JPOOL_PERMANENT, sizeof(jpeg_source_mgr)));
|
||||
|
||||
jpeg_source_mgr* src = cinfo->src;
|
||||
src->init_source = init_buffer_source;
|
||||
@ -262,16 +257,12 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
|
||||
{
|
||||
auto* cinfo = reinterpret_cast<jpeg_compress_struct*>(cinfo_p);
|
||||
|
||||
#if ( \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__))
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
jpeg_create_compress(cinfo);
|
||||
#if ( \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
static int const BUF_SIZE = 65536;
|
||||
@ -290,11 +281,9 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
|
||||
|
||||
jpeg_start_compress(cinfo, TRUE);
|
||||
|
||||
unsigned int width =
|
||||
cinfo->image_width * QIntC::to_uint(cinfo->input_components);
|
||||
unsigned int width = cinfo->image_width * QIntC::to_uint(cinfo->input_components);
|
||||
size_t expected_size = QIntC::to_size(cinfo->image_height) *
|
||||
QIntC::to_size(cinfo->image_width) *
|
||||
QIntC::to_size(cinfo->input_components);
|
||||
QIntC::to_size(cinfo->image_width) * QIntC::to_size(cinfo->input_components);
|
||||
if (b->getSize() != expected_size) {
|
||||
throw std::runtime_error(
|
||||
"Pl_DCT: image buffer size = " + std::to_string(b->getSize()) +
|
||||
@ -316,16 +305,12 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
|
||||
{
|
||||
auto* cinfo = reinterpret_cast<jpeg_decompress_struct*>(cinfo_p);
|
||||
|
||||
#if ( \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__))
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
jpeg_create_decompress(cinfo);
|
||||
#if ( \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
jpeg_buffer_src(cinfo, b);
|
||||
@ -333,10 +318,9 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
|
||||
(void)jpeg_read_header(cinfo, TRUE);
|
||||
(void)jpeg_calc_output_dimensions(cinfo);
|
||||
|
||||
unsigned int width =
|
||||
cinfo->output_width * QIntC::to_uint(cinfo->output_components);
|
||||
JSAMPARRAY buffer = (*cinfo->mem->alloc_sarray)(
|
||||
reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
|
||||
unsigned int width = cinfo->output_width * QIntC::to_uint(cinfo->output_components);
|
||||
JSAMPARRAY buffer =
|
||||
(*cinfo->mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
|
||||
|
||||
(void)jpeg_start_decompress(cinfo);
|
||||
while (cinfo->output_scanline < cinfo->output_height) {
|
||||
|
@ -54,10 +54,7 @@ Pl_Flate::Members::~Members()
|
||||
}
|
||||
|
||||
Pl_Flate::Pl_Flate(
|
||||
char const* identifier,
|
||||
Pipeline* next,
|
||||
action_e action,
|
||||
unsigned int out_bufsize_int) :
|
||||
char const* identifier, Pipeline* next, action_e action, unsigned int out_bufsize_int) :
|
||||
Pipeline(identifier, next),
|
||||
m(new Members(QIntC::to_size(out_bufsize_int), action))
|
||||
{
|
||||
@ -88,8 +85,7 @@ Pl_Flate::write(unsigned char const* data, size_t len)
|
||||
{
|
||||
if (m->outbuf == nullptr) {
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pl_Flate: write() called after finish() called");
|
||||
this->identifier + ": Pl_Flate: write() called after finish() called");
|
||||
}
|
||||
|
||||
// Write in chunks in case len is too big to fit in an int.
|
||||
@ -99,8 +95,7 @@ Pl_Flate::write(unsigned char const* data, size_t len)
|
||||
unsigned char const* buf = data;
|
||||
while (bytes_left > 0) {
|
||||
size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
|
||||
handleData(
|
||||
buf, bytes, (m->action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH));
|
||||
handleData(buf, bytes, (m->action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH));
|
||||
bytes_left -= bytes;
|
||||
buf += bytes;
|
||||
}
|
||||
@ -124,9 +119,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
|
||||
|
||||
// deflateInit and inflateInit are macros that use old-style
|
||||
// casts.
|
||||
#if ( \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__))
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
@ -135,9 +128,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
|
||||
} else {
|
||||
err = inflateInit(&zstream);
|
||||
}
|
||||
#if ( \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@ -171,8 +162,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
|
||||
// least one in qpdf's test suite). In some cases, we want
|
||||
// to know about this, because it indicates incorrect
|
||||
// compression, so call a callback if provided.
|
||||
this->warn(
|
||||
"input stream is complete but output may still be valid", err);
|
||||
this->warn("input stream is complete but output may still be valid", err);
|
||||
done = true;
|
||||
break;
|
||||
|
||||
@ -188,8 +178,7 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
|
||||
// needed, so we're done for now.
|
||||
done = true;
|
||||
}
|
||||
uLong ready =
|
||||
QIntC::to_ulong(m->out_bufsize - zstream.avail_out);
|
||||
uLong ready = QIntC::to_ulong(m->out_bufsize - zstream.avail_out);
|
||||
if (ready > 0) {
|
||||
this->getNext()->write(m->outbuf.get(), ready);
|
||||
zstream.next_out = m->outbuf.get();
|
||||
@ -249,10 +238,8 @@ Pl_Flate::checkError(char const* prefix, int error_code)
|
||||
{
|
||||
z_stream& zstream = *(static_cast<z_stream*>(m->zdata));
|
||||
if (error_code != Z_OK) {
|
||||
char const* action_str =
|
||||
(m->action == a_deflate ? "deflate" : "inflate");
|
||||
std::string msg =
|
||||
this->identifier + ": " + action_str + ": " + prefix + ": ";
|
||||
char const* action_str = (m->action == a_deflate ? "deflate" : "inflate");
|
||||
std::string msg = this->identifier + ": " + action_str + ": " + prefix + ": ";
|
||||
|
||||
if (zstream.msg) {
|
||||
msg += zstream.msg;
|
||||
@ -283,8 +270,7 @@ Pl_Flate::checkError(char const* prefix, int error_code)
|
||||
break;
|
||||
|
||||
default:
|
||||
msg += std::string("zlib unknown error (") +
|
||||
std::to_string(error_code) + ")";
|
||||
msg += std::string("zlib unknown error (") + std::to_string(error_code) + ")";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,7 @@ Pl_Function::Pl_Function(char const* identifier, Pipeline* next, writer_t fn) :
|
||||
{
|
||||
}
|
||||
|
||||
Pl_Function::Pl_Function(
|
||||
char const* identifier, Pipeline* next, writer_c_t fn, void* udata) :
|
||||
Pl_Function::Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata) :
|
||||
Pipeline(identifier, next),
|
||||
m(new Members(nullptr))
|
||||
{
|
||||
@ -22,14 +21,12 @@ Pl_Function::Pl_Function(
|
||||
int code = fn(data, len, udata);
|
||||
if (code != 0) {
|
||||
throw std::runtime_error(
|
||||
std::string(identifier) + " function returned code " +
|
||||
std::to_string(code));
|
||||
std::string(identifier) + " function returned code " + std::to_string(code));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Pl_Function::Pl_Function(
|
||||
char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata) :
|
||||
Pl_Function::Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata) :
|
||||
Pipeline(identifier, next),
|
||||
m(new Members(nullptr))
|
||||
{
|
||||
@ -37,8 +34,7 @@ Pl_Function::Pl_Function(
|
||||
int code = fn(reinterpret_cast<char const*>(data), len, udata);
|
||||
if (code != 0) {
|
||||
throw std::runtime_error(
|
||||
std::string(identifier) + " function returned code " +
|
||||
std::to_string(code));
|
||||
std::string(identifier) + " function returned code " + std::to_string(code));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -6,8 +6,7 @@
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
Pl_LZWDecoder::Pl_LZWDecoder(
|
||||
char const* identifier, Pipeline* next, bool early_code_change) :
|
||||
Pl_LZWDecoder::Pl_LZWDecoder(char const* identifier, Pipeline* next, bool early_code_change) :
|
||||
Pipeline(identifier, next),
|
||||
code_size(9),
|
||||
next(0),
|
||||
@ -90,15 +89,13 @@ Pl_LZWDecoder::getFirstChar(unsigned int code)
|
||||
} else if (code > 257) {
|
||||
unsigned int idx = code - 258;
|
||||
if (idx >= table.size()) {
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::getFirstChar: table overflow");
|
||||
throw std::runtime_error("Pl_LZWDecoder::getFirstChar: table overflow");
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
result = b.getBuffer()[0];
|
||||
} else {
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::getFirstChar called with invalid code (" +
|
||||
std::to_string(code) + ")");
|
||||
"Pl_LZWDecoder::getFirstChar called with invalid code (" + std::to_string(code) + ")");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -117,8 +114,7 @@ Pl_LZWDecoder::addToTable(unsigned char next)
|
||||
} else if (this->last_code > 257) {
|
||||
unsigned int idx = this->last_code - 258;
|
||||
if (idx >= table.size()) {
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::addToTable: table overflow");
|
||||
throw std::runtime_error("Pl_LZWDecoder::addToTable: table overflow");
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
last_data = b.getBuffer();
|
||||
@ -182,8 +178,7 @@ Pl_LZWDecoder::handleCode(unsigned int code)
|
||||
}
|
||||
addToTable(next);
|
||||
unsigned int change_idx = new_idx + code_change_delta;
|
||||
if ((change_idx == 511) || (change_idx == 1023) ||
|
||||
(change_idx == 2047)) {
|
||||
if ((change_idx == 511) || (change_idx == 1023) || (change_idx == 2047)) {
|
||||
++this->code_size;
|
||||
}
|
||||
}
|
||||
@ -194,8 +189,7 @@ Pl_LZWDecoder::handleCode(unsigned int code)
|
||||
} else {
|
||||
unsigned int idx = code - 258;
|
||||
if (idx >= table.size()) {
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::handleCode: table overflow");
|
||||
throw std::runtime_error("Pl_LZWDecoder::handleCode: table overflow");
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
getNext()->write(b.getBuffer(), b.getSize());
|
||||
|
@ -26,8 +26,7 @@ Pl_MD5::write(unsigned char const* buf, size_t len)
|
||||
unsigned char const* data = buf;
|
||||
while (bytes_left > 0) {
|
||||
size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
|
||||
this->md5.encodeDataIncrementally(
|
||||
reinterpret_cast<char const*>(data), bytes);
|
||||
this->md5.encodeDataIncrementally(reinterpret_cast<char const*>(data), bytes);
|
||||
bytes_left -= bytes;
|
||||
data += bytes;
|
||||
}
|
||||
|
@ -22,8 +22,7 @@ Pl_OStream::~Pl_OStream()
|
||||
void
|
||||
Pl_OStream::write(unsigned char const* buf, size_t len)
|
||||
{
|
||||
m->os.write(
|
||||
reinterpret_cast<char const*>(buf), static_cast<std::streamsize>(len));
|
||||
m->os.write(reinterpret_cast<char const*>(buf), static_cast<std::streamsize>(len));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -29,36 +29,28 @@ Pl_PNGFilter::Pl_PNGFilter(
|
||||
pos(0)
|
||||
{
|
||||
if (samples_per_pixel < 1) {
|
||||
throw std::runtime_error(
|
||||
"PNGFilter created with invalid samples_per_pixel");
|
||||
throw std::runtime_error("PNGFilter created with invalid samples_per_pixel");
|
||||
}
|
||||
if (!((bits_per_sample == 1) || (bits_per_sample == 2) ||
|
||||
(bits_per_sample == 4) || (bits_per_sample == 8) ||
|
||||
(bits_per_sample == 16))) {
|
||||
throw std::runtime_error(
|
||||
"PNGFilter created with invalid bits_per_sample not"
|
||||
if (!((bits_per_sample == 1) || (bits_per_sample == 2) || (bits_per_sample == 4) ||
|
||||
(bits_per_sample == 8) || (bits_per_sample == 16))) {
|
||||
throw std::runtime_error("PNGFilter created with invalid bits_per_sample not"
|
||||
" 1, 2, 4, 8, or 16");
|
||||
}
|
||||
this->bytes_per_pixel = ((bits_per_sample * samples_per_pixel) + 7) / 8;
|
||||
unsigned long long bpr =
|
||||
((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
|
||||
unsigned long long bpr = ((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
|
||||
if ((bpr == 0) || (bpr > (UINT_MAX - 1))) {
|
||||
throw std::runtime_error(
|
||||
"PNGFilter created with invalid columns value");
|
||||
throw std::runtime_error("PNGFilter created with invalid columns value");
|
||||
}
|
||||
this->bytes_per_row = bpr & UINT_MAX;
|
||||
this->buf1 =
|
||||
QUtil::make_shared_array<unsigned char>(this->bytes_per_row + 1);
|
||||
this->buf2 =
|
||||
QUtil::make_shared_array<unsigned char>(this->bytes_per_row + 1);
|
||||
this->buf1 = QUtil::make_shared_array<unsigned char>(this->bytes_per_row + 1);
|
||||
this->buf2 = QUtil::make_shared_array<unsigned char>(this->bytes_per_row + 1);
|
||||
memset(this->buf1.get(), 0, this->bytes_per_row + 1);
|
||||
memset(this->buf2.get(), 0, this->bytes_per_row + 1);
|
||||
this->cur_row = this->buf1.get();
|
||||
this->prev_row = this->buf2.get();
|
||||
|
||||
// number of bytes per incoming row
|
||||
this->incoming =
|
||||
(action == a_encode ? this->bytes_per_row : this->bytes_per_row + 1);
|
||||
this->incoming = (action == a_encode ? this->bytes_per_row : this->bytes_per_row + 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -197,8 +189,8 @@ Pl_PNGFilter::decodePaeth()
|
||||
upper_left = above_buffer[i - bpp];
|
||||
}
|
||||
|
||||
buffer[i] = static_cast<unsigned char>(
|
||||
buffer[i] + this->PaethPredictor(left, up, upper_left));
|
||||
buffer[i] =
|
||||
static_cast<unsigned char>(buffer[i] + this->PaethPredictor(left, up, upper_left));
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,8 +219,7 @@ Pl_PNGFilter::encodeRow()
|
||||
getNext()->write(&ch, 1);
|
||||
if (this->prev_row) {
|
||||
for (unsigned int i = 0; i < this->bytes_per_row; ++i) {
|
||||
ch = static_cast<unsigned char>(
|
||||
this->cur_row[i] - this->prev_row[i]);
|
||||
ch = static_cast<unsigned char>(this->cur_row[i] - this->prev_row[i]);
|
||||
getNext()->write(&ch, 1);
|
||||
}
|
||||
} else {
|
||||
|
@ -11,15 +11,12 @@ Pl_QPDFTokenizer::Members::Members() :
|
||||
}
|
||||
|
||||
Pl_QPDFTokenizer::Pl_QPDFTokenizer(
|
||||
char const* identifier,
|
||||
QPDFObjectHandle::TokenFilter* filter,
|
||||
Pipeline* next) :
|
||||
char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next) :
|
||||
Pipeline(identifier, next),
|
||||
m(new Members)
|
||||
{
|
||||
m->filter = filter;
|
||||
QPDFObjectHandle::TokenFilter::PipelineAccessor::setPipeline(
|
||||
m->filter, next);
|
||||
QPDFObjectHandle::TokenFilter::PipelineAccessor::setPipeline(m->filter, next);
|
||||
m->tokenizer.allowEOF();
|
||||
m->tokenizer.includeIgnorable();
|
||||
}
|
||||
@ -45,8 +42,8 @@ Pl_QPDFTokenizer::finish()
|
||||
new BufferInputSource("tokenizer data", m->buf.getBuffer(), true));
|
||||
|
||||
while (true) {
|
||||
QPDFTokenizer::Token token = m->tokenizer.readToken(
|
||||
input, "offset " + std::to_string(input->tell()), true);
|
||||
QPDFTokenizer::Token token =
|
||||
m->tokenizer.readToken(input, "offset " + std::to_string(input->tell()), true);
|
||||
m->filter->handleToken(token);
|
||||
if (token.getType() == QPDFTokenizer::tt_eof) {
|
||||
break;
|
||||
@ -56,15 +53,13 @@ Pl_QPDFTokenizer::finish()
|
||||
input->read(&ch, 1);
|
||||
m->filter->handleToken(
|
||||
// line-break
|
||||
QPDFTokenizer::Token(
|
||||
QPDFTokenizer::tt_space, std::string(1, ch)));
|
||||
QPDFTokenizer::Token(QPDFTokenizer::tt_space, std::string(1, ch)));
|
||||
QTC::TC("qpdf", "Pl_QPDFTokenizer found ID");
|
||||
m->tokenizer.expectInlineImage(input);
|
||||
}
|
||||
}
|
||||
m->filter->handleEOF();
|
||||
QPDFObjectHandle::TokenFilter::PipelineAccessor::setPipeline(
|
||||
m->filter, nullptr);
|
||||
QPDFObjectHandle::TokenFilter::PipelineAccessor::setPipeline(m->filter, nullptr);
|
||||
Pipeline* next = this->getNext(true);
|
||||
if (next) {
|
||||
next->finish();
|
||||
|
@ -19,17 +19,14 @@ void
|
||||
Pl_RC4::write(unsigned char const* data, size_t len)
|
||||
{
|
||||
if (this->outbuf == nullptr) {
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pl_RC4: write() called after finish() called");
|
||||
throw std::logic_error(this->identifier + ": Pl_RC4: write() called after finish() called");
|
||||
}
|
||||
|
||||
size_t bytes_left = len;
|
||||
unsigned char const* p = data;
|
||||
|
||||
while (bytes_left > 0) {
|
||||
size_t bytes =
|
||||
(bytes_left < this->out_bufsize ? bytes_left : out_bufsize);
|
||||
size_t bytes = (bytes_left < this->out_bufsize ? bytes_left : out_bufsize);
|
||||
bytes_left -= bytes;
|
||||
// lgtm[cpp/weak-cryptographic-algorithm]
|
||||
rc4.process(p, bytes, outbuf.get());
|
||||
|
@ -10,8 +10,7 @@ Pl_RunLength::Members::Members(action_e action) :
|
||||
{
|
||||
}
|
||||
|
||||
Pl_RunLength::Pl_RunLength(
|
||||
char const* identifier, Pipeline* next, action_e action) :
|
||||
Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, action_e action) :
|
||||
Pipeline(identifier, next),
|
||||
m(new Members(action))
|
||||
{
|
||||
@ -38,17 +37,12 @@ Pl_RunLength::encode(unsigned char const* data, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if ((m->state == st_top) != (m->length <= 1)) {
|
||||
throw std::logic_error(
|
||||
"Pl_RunLength::encode: state/length inconsistency");
|
||||
throw std::logic_error("Pl_RunLength::encode: state/length inconsistency");
|
||||
}
|
||||
unsigned char ch = data[i];
|
||||
if ((m->length > 0) &&
|
||||
((m->state == st_copying) || (m->length < 128)) &&
|
||||
if ((m->length > 0) && ((m->state == st_copying) || (m->length < 128)) &&
|
||||
(ch == m->buf[m->length - 1])) {
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"Pl_RunLength: switch to run",
|
||||
(m->length == 128) ? 0 : 1);
|
||||
QTC::TC("libtests", "Pl_RunLength: switch to run", (m->length == 128) ? 0 : 1);
|
||||
if (m->state == st_copying) {
|
||||
--m->length;
|
||||
flush_encode();
|
||||
@ -124,8 +118,7 @@ Pl_RunLength::flush_encode()
|
||||
}
|
||||
if (m->state == st_run) {
|
||||
if ((m->length < 2) || (m->length > 128)) {
|
||||
throw std::logic_error(
|
||||
"Pl_RunLength: invalid length in flush_encode for run");
|
||||
throw std::logic_error("Pl_RunLength: invalid length in flush_encode for run");
|
||||
}
|
||||
auto ch = static_cast<unsigned char>(257 - m->length);
|
||||
this->getNext()->write(&ch, 1);
|
||||
|
@ -51,8 +51,7 @@ void
|
||||
Pl_SHA2::resetBits(int bits)
|
||||
{
|
||||
if (this->in_progress) {
|
||||
throw std::logic_error(
|
||||
"bit reset requested for in-progress SHA2 Pipeline");
|
||||
throw std::logic_error("bit reset requested for in-progress SHA2 Pipeline");
|
||||
}
|
||||
this->crypto = QPDFCryptoProvider::getImpl();
|
||||
this->crypto->SHA2_init(bits);
|
||||
@ -62,8 +61,7 @@ std::string
|
||||
Pl_SHA2::getRawDigest()
|
||||
{
|
||||
if (this->in_progress) {
|
||||
throw std::logic_error(
|
||||
"digest requested for in-progress SHA2 Pipeline");
|
||||
throw std::logic_error("digest requested for in-progress SHA2 Pipeline");
|
||||
}
|
||||
return this->crypto->SHA2_digest();
|
||||
}
|
||||
@ -72,8 +70,7 @@ std::string
|
||||
Pl_SHA2::getHexDigest()
|
||||
{
|
||||
if (this->in_progress) {
|
||||
throw std::logic_error(
|
||||
"digest requested for in-progress SHA2 Pipeline");
|
||||
throw std::logic_error("digest requested for in-progress SHA2 Pipeline");
|
||||
}
|
||||
return QUtil::hex_encode(getRawDigest());
|
||||
}
|
||||
|
@ -30,8 +30,7 @@ Pl_StdioFile::write(unsigned char const* buf, size_t len)
|
||||
while (len > 0) {
|
||||
so_far = fwrite(buf, 1, len, m->file);
|
||||
if (so_far == 0) {
|
||||
QUtil::throw_system_error(
|
||||
this->identifier + ": Pl_StdioFile::write");
|
||||
QUtil::throw_system_error(this->identifier + ": Pl_StdioFile::write");
|
||||
} else {
|
||||
buf += so_far;
|
||||
len -= so_far;
|
||||
@ -43,7 +42,6 @@ void
|
||||
Pl_StdioFile::finish()
|
||||
{
|
||||
if ((fflush(m->file) == -1) && (errno == EBADF)) {
|
||||
throw std::logic_error(
|
||||
this->identifier + ": Pl_StdioFile::finish: stream already closed");
|
||||
throw std::logic_error(this->identifier + ": Pl_StdioFile::finish: stream already closed");
|
||||
}
|
||||
}
|
||||
|
@ -25,23 +25,17 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
|
||||
pos(0)
|
||||
{
|
||||
if (samples_per_pixel < 1) {
|
||||
throw std::runtime_error(
|
||||
"TIFFPredictor created with invalid samples_per_pixel");
|
||||
throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel");
|
||||
}
|
||||
if ((bits_per_sample < 1) ||
|
||||
(bits_per_sample > (8 * (sizeof(unsigned long long))))) {
|
||||
throw std::runtime_error(
|
||||
"TIFFPredictor created with invalid bits_per_sample");
|
||||
if ((bits_per_sample < 1) || (bits_per_sample > (8 * (sizeof(unsigned long long))))) {
|
||||
throw std::runtime_error("TIFFPredictor created with invalid bits_per_sample");
|
||||
}
|
||||
unsigned long long bpr =
|
||||
((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
|
||||
unsigned long long bpr = ((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
|
||||
if ((bpr == 0) || (bpr > (UINT_MAX - 1))) {
|
||||
throw std::runtime_error(
|
||||
"TIFFPredictor created with invalid columns value");
|
||||
throw std::runtime_error("TIFFPredictor created with invalid columns value");
|
||||
}
|
||||
this->bytes_per_row = bpr & UINT_MAX;
|
||||
this->cur_row =
|
||||
QUtil::make_shared_array<unsigned char>(this->bytes_per_row);
|
||||
this->cur_row = QUtil::make_shared_array<unsigned char>(this->bytes_per_row);
|
||||
memset(this->cur_row.get(), 0, this->bytes_per_row);
|
||||
}
|
||||
|
||||
@ -72,10 +66,7 @@ Pl_TIFFPredictor::write(unsigned char const* data, size_t len)
|
||||
void
|
||||
Pl_TIFFPredictor::processRow()
|
||||
{
|
||||
QTC::TC(
|
||||
"libtests",
|
||||
"Pl_TIFFPredictor processRow",
|
||||
(action == a_decode ? 0 : 1));
|
||||
QTC::TC("libtests", "Pl_TIFFPredictor processRow", (action == a_decode ? 0 : 1));
|
||||
BitWriter bw(this->getNext());
|
||||
BitStream in(this->cur_row.get(), this->bytes_per_row);
|
||||
std::vector<long long> prev;
|
||||
|
340
libqpdf/QPDF.cc
340
libqpdf/QPDF.cc
@ -105,8 +105,7 @@ namespace
|
||||
void
|
||||
throwException()
|
||||
{
|
||||
throw std::logic_error(
|
||||
"QPDF operation attempted on a QPDF object with no input "
|
||||
throw std::logic_error("QPDF operation attempted on a QPDF object with no input "
|
||||
"source."
|
||||
" QPDF operations are invalid before processFile (or another"
|
||||
" process method) or after closeInputSource");
|
||||
@ -130,8 +129,7 @@ QPDF::ForeignStreamData::ForeignStreamData(
|
||||
{
|
||||
}
|
||||
|
||||
QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(
|
||||
QPDF& destination_qpdf) :
|
||||
QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(QPDF& destination_qpdf) :
|
||||
QPDFObjectHandle::StreamDataProvider(true),
|
||||
destination_qpdf(destination_qpdf)
|
||||
{
|
||||
@ -139,10 +137,7 @@ QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(
|
||||
|
||||
bool
|
||||
QPDF::CopiedStreamDataProvider::provideStreamData(
|
||||
QPDFObjGen const& og,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry)
|
||||
QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry)
|
||||
{
|
||||
std::shared_ptr<ForeignStreamData> foreign_data = foreign_stream_data[og];
|
||||
bool result = false;
|
||||
@ -154,8 +149,7 @@ QPDF::CopiedStreamDataProvider::provideStreamData(
|
||||
auto foreign_stream = foreign_streams[og];
|
||||
result = foreign_stream.pipeStreamData(
|
||||
pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry);
|
||||
QTC::TC(
|
||||
"qpdf", "QPDF copy foreign with foreign_stream", result ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDF copy foreign with foreign_stream", result ? 0 : 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -169,8 +163,7 @@ QPDF::CopiedStreamDataProvider::registerForeignStream(
|
||||
|
||||
void
|
||||
QPDF::CopiedStreamDataProvider::registerForeignStream(
|
||||
QPDFObjGen const& local_og,
|
||||
std::shared_ptr<ForeignStreamData> foreign_stream)
|
||||
QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData> foreign_stream)
|
||||
{
|
||||
this->foreign_stream_data[local_og] = foreign_stream;
|
||||
}
|
||||
@ -269,8 +262,7 @@ QPDF::processFile(char const* filename, char const* password)
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::processFile(
|
||||
char const* description, FILE* filep, bool close_file, char const* password)
|
||||
QPDF::processFile(char const* description, FILE* filep, bool close_file, char const* password)
|
||||
{
|
||||
auto* fi = new FileInputSource(description, filep, close_file);
|
||||
processInputSource(std::shared_ptr<InputSource>(fi), password);
|
||||
@ -278,24 +270,18 @@ QPDF::processFile(
|
||||
|
||||
void
|
||||
QPDF::processMemoryFile(
|
||||
char const* description,
|
||||
char const* buf,
|
||||
size_t length,
|
||||
char const* password)
|
||||
char const* description, char const* buf, size_t length, char const* password)
|
||||
{
|
||||
processInputSource(
|
||||
std::shared_ptr<InputSource>(
|
||||
// line-break
|
||||
new BufferInputSource(
|
||||
description,
|
||||
new Buffer(QUtil::unsigned_char_pointer(buf), length),
|
||||
true)),
|
||||
description, new Buffer(QUtil::unsigned_char_pointer(buf), length), true)),
|
||||
password);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::processInputSource(
|
||||
std::shared_ptr<InputSource> source, char const* password)
|
||||
QPDF::processInputSource(std::shared_ptr<InputSource> source, char const* password)
|
||||
{
|
||||
m->file = source;
|
||||
parse(password);
|
||||
@ -321,8 +307,7 @@ QPDF::emptyPDF()
|
||||
|
||||
void
|
||||
QPDF::registerStreamFilter(
|
||||
std::string const& filter_name,
|
||||
std::function<std::shared_ptr<QPDFStreamFilter>()> factory)
|
||||
std::string const& filter_name, std::function<std::shared_ptr<QPDFStreamFilter>()> factory)
|
||||
{
|
||||
QPDF_Stream::registerStreamFilter(filter_name, factory);
|
||||
}
|
||||
@ -434,8 +419,7 @@ QPDF::findHeader()
|
||||
// offsets in the file are such that 0 points to the
|
||||
// beginning of the header.
|
||||
QTC::TC("qpdf", "QPDF global offset");
|
||||
m->file = std::shared_ptr<InputSource>(
|
||||
new OffsetInputSource(m->file, global_offset));
|
||||
m->file = std::shared_ptr<InputSource>(new OffsetInputSource(m->file, global_offset));
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
@ -444,8 +428,7 @@ QPDF::findHeader()
|
||||
bool
|
||||
QPDF::findStartxref()
|
||||
{
|
||||
if (readToken(m->file).isWord("startxref") &&
|
||||
readToken(m->file).isInteger()) {
|
||||
if (readToken(m->file).isWord("startxref") && readToken(m->file).isInteger()) {
|
||||
// Position in front of offset token
|
||||
m->file->seek(m->file->getLastOffset(), SEEK_SET);
|
||||
return true;
|
||||
@ -479,8 +462,7 @@ QPDF::parse(char const* password)
|
||||
PatternFinder sf(*this, &QPDF::findStartxref);
|
||||
qpdf_offset_t xref_offset = 0;
|
||||
if (m->file->findLast("startxref", start_offset, 0, sf)) {
|
||||
xref_offset =
|
||||
QUtil::string_to_ll(readToken(m->file).getValue().c_str());
|
||||
xref_offset = QUtil::string_to_ll(readToken(m->file).getValue().c_str());
|
||||
}
|
||||
|
||||
try {
|
||||
@ -493,8 +475,7 @@ QPDF::parse(char const* password)
|
||||
} catch (QPDFExc&) {
|
||||
throw;
|
||||
} catch (std::exception& e) {
|
||||
throw damagedPDF(
|
||||
"", 0, std::string("error reading xref: ") + e.what());
|
||||
throw damagedPDF("", 0, std::string("error reading xref: ") + e.what());
|
||||
}
|
||||
} catch (QPDFExc& e) {
|
||||
if (m->attempt_recovery) {
|
||||
@ -515,8 +496,7 @@ QPDF::inParse(bool v)
|
||||
if (m->in_parse == v) {
|
||||
// This happens if QPDFParser::parse tries to
|
||||
// resolve an indirect object while it is parsing.
|
||||
throw std::logic_error(
|
||||
"QPDF: re-entrant parsing detected. This is a qpdf bug."
|
||||
throw std::logic_error("QPDF: re-entrant parsing detected. This is a qpdf bug."
|
||||
" Please report at https://github.com/qpdf/qpdf/issues.");
|
||||
}
|
||||
m->in_parse = v;
|
||||
@ -590,22 +570,19 @@ QPDF::reconstruct_xref(QPDFExc& e)
|
||||
qpdf_offset_t next_line_start = m->file->tell();
|
||||
m->file->seek(line_start, SEEK_SET);
|
||||
QPDFTokenizer::Token t1 = readToken(m->file, MAX_LEN);
|
||||
qpdf_offset_t token_start =
|
||||
m->file->tell() - toO(t1.getValue().length());
|
||||
qpdf_offset_t token_start = m->file->tell() - toO(t1.getValue().length());
|
||||
if (token_start >= next_line_start) {
|
||||
// don't process yet -- wait until we get to the line
|
||||
// containing this token
|
||||
} else if (t1.isInteger()) {
|
||||
QPDFTokenizer::Token t2 = readToken(m->file, MAX_LEN);
|
||||
if ((t2.isInteger()) &&
|
||||
(readToken(m->file, MAX_LEN).isWord("obj"))) {
|
||||
if ((t2.isInteger()) && (readToken(m->file, MAX_LEN).isWord("obj"))) {
|
||||
int obj = QUtil::string_to_int(t1.getValue().c_str());
|
||||
int gen = QUtil::string_to_int(t2.getValue().c_str());
|
||||
insertXrefEntry(obj, 1, token_start, gen, true);
|
||||
}
|
||||
} else if (!m->trailer.isInitialized() && t1.isWord("trailer")) {
|
||||
QPDFObjectHandle t =
|
||||
readObject(m->file, "trailer", QPDFObjGen(), false);
|
||||
QPDFObjectHandle t = readObject(m->file, "trailer", QPDFObjGen(), false);
|
||||
if (!t.isDictionary()) {
|
||||
// Oh well. It was worth a try.
|
||||
} else {
|
||||
@ -623,10 +600,7 @@ QPDF::reconstruct_xref(QPDFExc& e)
|
||||
// with bad startxref pointers even when they have object
|
||||
// streams.
|
||||
|
||||
throw damagedPDF(
|
||||
"",
|
||||
0,
|
||||
"unable to find trailer dictionary while recovering damaged file");
|
||||
throw damagedPDF("", 0, "unable to find trailer dictionary while recovering damaged file");
|
||||
}
|
||||
|
||||
// We could iterate through the objects looking for streams and
|
||||
@ -666,10 +640,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDF eof skipping spaces before xref",
|
||||
skipped_space ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDF eof skipping spaces before xref", skipped_space ? 0 : 1);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
@ -681,8 +652,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
|
||||
if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) {
|
||||
if (skipped_space) {
|
||||
QTC::TC("qpdf", "QPDF xref skipped space");
|
||||
warn(damagedPDF(
|
||||
"", 0, "extraneous whitespace seen before xref"));
|
||||
warn(damagedPDF("", 0, "extraneous whitespace seen before xref"));
|
||||
}
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
@ -724,8 +694,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
|
||||
"",
|
||||
0,
|
||||
("reported number of objects (" + std::to_string(size) +
|
||||
") is not one plus the highest object number (" +
|
||||
std::to_string(max_obj) + ")")));
|
||||
") is not one plus the highest object number (" + std::to_string(max_obj) + ")")));
|
||||
}
|
||||
|
||||
// We no longer need the deleted_objects table, so go ahead and
|
||||
@ -782,8 +751,7 @@ QPDF::parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes)
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF::parse_xrefEntry(
|
||||
std::string const& line, qpdf_offset_t& f1, int& f2, char& type)
|
||||
QPDF::parse_xrefEntry(std::string const& line, qpdf_offset_t& f1, int& f2, char& type)
|
||||
{
|
||||
// is_space and is_digit both return false on '\0', so this will
|
||||
// not overrun the null-terminated buffer.
|
||||
@ -891,8 +859,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
||||
if (!parse_xrefEntry(xref_entry, f1, f2, type)) {
|
||||
QTC::TC("qpdf", "QPDF invalid xref entry");
|
||||
throw damagedPDF(
|
||||
"xref table",
|
||||
"invalid xref entry (obj=" + std::to_string(i) + ")");
|
||||
"xref table", "invalid xref entry (obj=" + std::to_string(i) + ")");
|
||||
}
|
||||
if (type == 'f') {
|
||||
// Save deleted items until after we've checked the
|
||||
@ -911,8 +878,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
||||
}
|
||||
|
||||
// Set offset to previous xref table if any
|
||||
QPDFObjectHandle cur_trailer =
|
||||
readObject(m->file, "trailer", QPDFObjGen(), false);
|
||||
QPDFObjectHandle cur_trailer = readObject(m->file, "trailer", QPDFObjGen(), false);
|
||||
if (!cur_trailer.isDictionary()) {
|
||||
QTC::TC("qpdf", "QPDF missing trailer");
|
||||
throw damagedPDF("", "expected trailer dictionary");
|
||||
@ -927,8 +893,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
||||
}
|
||||
if (!m->trailer.getKey("/Size").isInteger()) {
|
||||
QTC::TC("qpdf", "QPDF trailer size not integer");
|
||||
throw damagedPDF(
|
||||
"trailer", "/Size key in trailer dictionary is not an integer");
|
||||
throw damagedPDF("trailer", "/Size key in trailer dictionary is not an integer");
|
||||
}
|
||||
}
|
||||
|
||||
@ -940,11 +905,9 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
||||
// Read the xref stream but disregard any return value
|
||||
// -- we'll use our trailer's /Prev key instead of the
|
||||
// xref stream's.
|
||||
(void)read_xrefStream(
|
||||
cur_trailer.getKey("/XRefStm").getIntValue());
|
||||
(void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue());
|
||||
} else {
|
||||
throw damagedPDF(
|
||||
"xref stream", xref_offset, "invalid /XRefStm");
|
||||
throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -957,8 +920,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
||||
if (cur_trailer.hasKey("/Prev")) {
|
||||
if (!cur_trailer.getKey("/Prev").isInteger()) {
|
||||
QTC::TC("qpdf", "QPDF trailer prev not integer");
|
||||
throw damagedPDF(
|
||||
"trailer", "/Prev key in trailer dictionary is not an integer");
|
||||
throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
|
||||
}
|
||||
QTC::TC("qpdf", "QPDF prev key in trailer dictionary");
|
||||
xref_offset = cur_trailer.getKey("/Prev").getIntValue();
|
||||
@ -977,13 +939,8 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset)
|
||||
QPDFObjGen x_og;
|
||||
QPDFObjectHandle xref_obj;
|
||||
try {
|
||||
xref_obj = readObjectAtOffset(
|
||||
false,
|
||||
xref_offset,
|
||||
"xref stream",
|
||||
QPDFObjGen(0, 0),
|
||||
x_og,
|
||||
true);
|
||||
xref_obj =
|
||||
readObjectAtOffset(false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og, true);
|
||||
} catch (QPDFExc&) {
|
||||
// ignore -- report error below
|
||||
}
|
||||
@ -1008,12 +965,9 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
QPDFObjectHandle dict = xref_obj.getDict();
|
||||
QPDFObjectHandle W_obj = dict.getKey("/W");
|
||||
QPDFObjectHandle Index_obj = dict.getKey("/Index");
|
||||
if (!(W_obj.isArray() && (W_obj.getArrayNItems() >= 3) &&
|
||||
W_obj.getArrayItem(0).isInteger() &&
|
||||
W_obj.getArrayItem(1).isInteger() &&
|
||||
W_obj.getArrayItem(2).isInteger() &&
|
||||
dict.getKey("/Size").isInteger() &&
|
||||
(Index_obj.isArray() || Index_obj.isNull()))) {
|
||||
if (!(W_obj.isArray() && (W_obj.getArrayNItems() >= 3) && W_obj.getArrayItem(0).isInteger() &&
|
||||
W_obj.getArrayItem(1).isInteger() && W_obj.getArrayItem(2).isInteger() &&
|
||||
dict.getKey("/Size").isInteger() && (Index_obj.isArray() || Index_obj.isNull()))) {
|
||||
throw damagedPDF(
|
||||
"xref stream",
|
||||
xref_offset,
|
||||
@ -1035,12 +989,9 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
}
|
||||
if (entry_size == 0) {
|
||||
throw damagedPDF(
|
||||
"xref stream",
|
||||
xref_offset,
|
||||
"Cross-reference stream's /W indicates entry size of 0");
|
||||
"xref stream", xref_offset, "Cross-reference stream's /W indicates entry size of 0");
|
||||
}
|
||||
unsigned long long max_num_entries =
|
||||
static_cast<unsigned long long>(-1) / entry_size;
|
||||
unsigned long long max_num_entries = static_cast<unsigned long long>(-1) / entry_size;
|
||||
|
||||
std::vector<long long> indx;
|
||||
if (Index_obj.isArray()) {
|
||||
@ -1059,8 +1010,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
throw damagedPDF(
|
||||
"xref stream",
|
||||
xref_offset,
|
||||
("Cross-reference stream's /Index's item " +
|
||||
std::to_string(i) + " is not an integer"));
|
||||
("Cross-reference stream's /Index's item " + std::to_string(i) +
|
||||
" is not an integer"));
|
||||
}
|
||||
}
|
||||
QTC::TC("qpdf", "QPDF xref /Index is array", n_index == 2 ? 0 : 1);
|
||||
@ -1078,8 +1029,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
"xref stream",
|
||||
xref_offset,
|
||||
("Cross-reference stream claims to contain too many entries: " +
|
||||
std::to_string(indx.at(i)) + " " +
|
||||
std::to_string(max_num_entries) + " " +
|
||||
std::to_string(indx.at(i)) + " " + std::to_string(max_num_entries) + " " +
|
||||
std::to_string(num_entries)));
|
||||
}
|
||||
num_entries += toS(indx.at(i));
|
||||
@ -1097,8 +1047,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
"xref stream",
|
||||
xref_offset,
|
||||
("Cross-reference stream data has the wrong size; expected = " +
|
||||
std::to_string(expected_size) +
|
||||
"; actual = " + std::to_string(actual_size)));
|
||||
std::to_string(expected_size) + "; actual = " + std::to_string(actual_size)));
|
||||
if (expected_size > actual_size) {
|
||||
throw x;
|
||||
} else {
|
||||
@ -1137,8 +1086,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
// an uncompressed object record, in which case the generation
|
||||
// number appears as the third field.
|
||||
int obj = toI(indx.at(cur_chunk));
|
||||
if ((obj < 0) ||
|
||||
((std::numeric_limits<int>::max() - obj) < chunk_count)) {
|
||||
if ((obj < 0) || ((std::numeric_limits<int>::max() - obj) < chunk_count)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "adding " << chunk_count << " to " << obj
|
||||
@ -1181,8 +1129,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
|
||||
if (dict.hasKey("/Prev")) {
|
||||
if (!dict.getKey("/Prev").isInteger()) {
|
||||
throw damagedPDF(
|
||||
"xref stream",
|
||||
"/Prev key in xref stream dictionary is not an integer");
|
||||
"xref stream", "/Prev key in xref stream dictionary is not an integer");
|
||||
}
|
||||
QTC::TC("qpdf", "QPDF prev key in xref stream dictionary");
|
||||
xref_offset = dict.getKey("/Prev").getIntValue();
|
||||
@ -1241,9 +1188,7 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite)
|
||||
break;
|
||||
|
||||
default:
|
||||
throw damagedPDF(
|
||||
"xref stream",
|
||||
"unknown xref stream entry type " + std::to_string(f0));
|
||||
throw damagedPDF("xref stream", "unknown xref stream entry type " + std::to_string(f0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1262,8 +1207,7 @@ QPDF::showXRefTable()
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*m->log->getInfo()
|
||||
<< "compressed; stream = " << entry.getObjStreamNumber()
|
||||
*m->log->getInfo() << "compressed; stream = " << entry.getObjStreamNumber()
|
||||
<< ", index = " << entry.getObjStreamIndex();
|
||||
break;
|
||||
|
||||
@ -1337,8 +1281,7 @@ QPDF::getAllObjects()
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::setLastObjectDescription(
|
||||
std::string const& description, QPDFObjGen const& og)
|
||||
QPDF::setLastObjectDescription(std::string const& description, QPDFObjGen const& og)
|
||||
{
|
||||
m->last_object_description.clear();
|
||||
if (!description.empty()) {
|
||||
@ -1369,16 +1312,13 @@ QPDF::readObject(
|
||||
decrypter_ph = std::make_shared<StringDecrypter>(this, og);
|
||||
decrypter = decrypter_ph.get();
|
||||
}
|
||||
auto object =
|
||||
QPDFParser(
|
||||
input, m->last_object_description, m->tokenizer, decrypter, this)
|
||||
auto object = QPDFParser(input, m->last_object_description, m->tokenizer, decrypter, this)
|
||||
.parse(empty, false);
|
||||
if (empty) {
|
||||
// Nothing in the PDF spec appears to allow empty objects, but
|
||||
// they have been encountered in actual PDF files and Adobe
|
||||
// Reader appears to ignore them.
|
||||
warn(damagedPDF(
|
||||
input, input->getLastOffset(), "empty object treated as null"));
|
||||
warn(damagedPDF(input, input->getLastOffset(), "empty object treated as null"));
|
||||
} else if (object.isDictionary() && (!in_object_stream)) {
|
||||
// check for stream
|
||||
qpdf_offset_t cur_offset = input->tell();
|
||||
@ -1428,9 +1368,7 @@ QPDF::readObject(
|
||||
}
|
||||
} else if (QUtil::is_space(ch)) {
|
||||
warn(damagedPDF(
|
||||
input,
|
||||
input->tell(),
|
||||
"stream keyword followed by extraneous whitespace"));
|
||||
input, input->tell(), "stream keyword followed by extraneous whitespace"));
|
||||
done = false;
|
||||
} else {
|
||||
QTC::TC("qpdf", "QPDF stream without newline");
|
||||
@ -1450,13 +1388,11 @@ QPDF::readObject(
|
||||
size_t length = 0;
|
||||
|
||||
try {
|
||||
std::map<std::string, QPDFObjectHandle> dict =
|
||||
object.getDictAsMap();
|
||||
std::map<std::string, QPDFObjectHandle> dict = object.getDictAsMap();
|
||||
|
||||
if (dict.count("/Length") == 0) {
|
||||
QTC::TC("qpdf", "QPDF stream without length");
|
||||
throw damagedPDF(
|
||||
input, offset, "stream dictionary lacks /Length key");
|
||||
throw damagedPDF(input, offset, "stream dictionary lacks /Length key");
|
||||
}
|
||||
|
||||
QPDFObjectHandle length_obj = dict["/Length"];
|
||||
@ -1475,8 +1411,7 @@ QPDF::readObject(
|
||||
input->seek(toO(length), SEEK_CUR);
|
||||
if (!readToken(input).isWord("endstream")) {
|
||||
QTC::TC("qpdf", "QPDF missing endstream");
|
||||
throw damagedPDF(
|
||||
input, input->getLastOffset(), "expected endstream");
|
||||
throw damagedPDF(input, input->getLastOffset(), "expected endstream");
|
||||
}
|
||||
} catch (QPDFExc& e) {
|
||||
if (m->attempt_recovery) {
|
||||
@ -1486,9 +1421,7 @@ QPDF::readObject(
|
||||
throw;
|
||||
}
|
||||
}
|
||||
object = newIndirect(
|
||||
og,
|
||||
QPDF_Stream::create(this, og, object, stream_offset, length));
|
||||
object = newIndirect(og, QPDF_Stream::create(this, og, object, stream_offset, length));
|
||||
} else {
|
||||
input->seek(cur_offset, SEEK_SET);
|
||||
}
|
||||
@ -1514,14 +1447,11 @@ QPDF::findEndstream()
|
||||
|
||||
size_t
|
||||
QPDF::recoverStreamLength(
|
||||
std::shared_ptr<InputSource> input,
|
||||
QPDFObjGen const& og,
|
||||
qpdf_offset_t stream_offset)
|
||||
std::shared_ptr<InputSource> input, QPDFObjGen const& og, qpdf_offset_t stream_offset)
|
||||
{
|
||||
// Try to reconstruct stream length by looking for
|
||||
// endstream or endobj
|
||||
warn(damagedPDF(
|
||||
input, stream_offset, "attempting to recover stream length"));
|
||||
warn(damagedPDF(input, stream_offset, "attempting to recover stream length"));
|
||||
|
||||
PatternFinder ef(*this, &QPDF::findEndstream);
|
||||
size_t length = 0;
|
||||
@ -1544,8 +1474,7 @@ QPDF::recoverStreamLength(
|
||||
if (entry.getType() == 1) {
|
||||
qpdf_offset_t obj_offset = entry.getOffset();
|
||||
if ((obj_offset > stream_offset) &&
|
||||
((this_obj_offset == 0) ||
|
||||
(this_obj_offset > obj_offset))) {
|
||||
((this_obj_offset == 0) || (this_obj_offset > obj_offset))) {
|
||||
this_obj_offset = obj_offset;
|
||||
this_og = iter.first;
|
||||
}
|
||||
@ -1562,14 +1491,10 @@ QPDF::recoverStreamLength(
|
||||
|
||||
if (length == 0) {
|
||||
warn(damagedPDF(
|
||||
input,
|
||||
stream_offset,
|
||||
"unable to recover stream data; treating stream as empty"));
|
||||
input, stream_offset, "unable to recover stream data; treating stream as empty"));
|
||||
} else {
|
||||
warn(damagedPDF(
|
||||
input,
|
||||
stream_offset,
|
||||
"recovered stream length: " + std::to_string(length)));
|
||||
warn(
|
||||
damagedPDF(input, stream_offset, "recovered stream length: " + std::to_string(length)));
|
||||
}
|
||||
|
||||
QTC::TC("qpdf", "QPDF recovered stream length");
|
||||
@ -1579,8 +1504,7 @@ QPDF::recoverStreamLength(
|
||||
QPDFTokenizer::Token
|
||||
QPDF::readToken(std::shared_ptr<InputSource> input, size_t max_len)
|
||||
{
|
||||
return m->tokenizer.readToken(
|
||||
input, m->last_object_description, true, max_len);
|
||||
return m->tokenizer.readToken(input, m->last_object_description, true, max_len);
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
@ -1650,8 +1574,7 @@ QPDF::readObjectAtOffset(
|
||||
}
|
||||
if (check_og && (exp_og != og)) {
|
||||
QTC::TC("qpdf", "QPDF err wrong objid/generation");
|
||||
QPDFExc e =
|
||||
damagedPDF(offset, "expected " + exp_og.unparse(' ') + " obj");
|
||||
QPDFExc e = damagedPDF(offset, "expected " + exp_og.unparse(' ') + " obj");
|
||||
if (try_recovery) {
|
||||
// Will be retried below
|
||||
throw e;
|
||||
@ -1665,11 +1588,10 @@ QPDF::readObjectAtOffset(
|
||||
if (try_recovery) {
|
||||
// Try again after reconstructing xref table
|
||||
reconstruct_xref(e);
|
||||
if (m->xref_table.count(exp_og) &&
|
||||
(m->xref_table[exp_og].getType() == 1)) {
|
||||
if (m->xref_table.count(exp_og) && (m->xref_table[exp_og].getType() == 1)) {
|
||||
qpdf_offset_t new_offset = m->xref_table[exp_og].getOffset();
|
||||
QPDFObjectHandle result = readObjectAtOffset(
|
||||
false, new_offset, description, exp_og, og, false);
|
||||
QPDFObjectHandle result =
|
||||
readObjectAtOffset(false, new_offset, description, exp_og, og, false);
|
||||
QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset");
|
||||
return result;
|
||||
} else {
|
||||
@ -1777,8 +1699,7 @@ QPDF::resolve(QPDFObjGen og)
|
||||
// indirectly in some key that has to be resolved during
|
||||
// object parsing, such as stream length.
|
||||
QTC::TC("qpdf", "QPDF recursion loop in resolve");
|
||||
warn(damagedPDF(
|
||||
"", "loop detected resolving object " + og.unparse(' ')));
|
||||
warn(damagedPDF("", "loop detected resolving object " + og.unparse(' ')));
|
||||
updateCache(og, QPDF_Null::create(), -1, -1);
|
||||
return;
|
||||
}
|
||||
@ -1793,8 +1714,7 @@ QPDF::resolve(QPDFObjGen og)
|
||||
qpdf_offset_t offset = entry.getOffset();
|
||||
// Object stored in cache by readObjectAtOffset
|
||||
QPDFObjGen a_og;
|
||||
QPDFObjectHandle oh =
|
||||
readObjectAtOffset(true, offset, "", og, a_og, false);
|
||||
QPDFObjectHandle oh = readObjectAtOffset(true, offset, "", og, a_og, false);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1804,19 +1724,13 @@ QPDF::resolve(QPDFObjGen og)
|
||||
|
||||
default:
|
||||
throw damagedPDF(
|
||||
"",
|
||||
0,
|
||||
("object " + og.unparse('/') +
|
||||
" has unexpected xref entry type"));
|
||||
"", 0, ("object " + og.unparse('/') + " has unexpected xref entry type"));
|
||||
}
|
||||
} catch (QPDFExc& e) {
|
||||
warn(e);
|
||||
} catch (std::exception& e) {
|
||||
warn(damagedPDF(
|
||||
"",
|
||||
0,
|
||||
("object " + og.unparse('/') +
|
||||
": error reading object: " + e.what())));
|
||||
"", 0, ("object " + og.unparse('/') + ": error reading object: " + e.what())));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1841,8 +1755,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
|
||||
QPDFObjectHandle obj_stream = getObjectByID(obj_stream_number, 0);
|
||||
if (!obj_stream.isStream()) {
|
||||
throw damagedPDF(
|
||||
"supposed object stream " + std::to_string(obj_stream_number) +
|
||||
" is not a stream");
|
||||
"supposed object stream " + std::to_string(obj_stream_number) + " is not a stream");
|
||||
}
|
||||
|
||||
// For linearization data in the object, use the data from the
|
||||
@ -1855,14 +1768,12 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
|
||||
if (!dict.isDictionaryOfType("/ObjStm")) {
|
||||
QTC::TC("qpdf", "QPDF ERR object stream with wrong type");
|
||||
warn(damagedPDF(
|
||||
"supposed object stream " + std::to_string(obj_stream_number) +
|
||||
" has wrong type"));
|
||||
"supposed object stream " + std::to_string(obj_stream_number) + " has wrong type"));
|
||||
}
|
||||
|
||||
if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) {
|
||||
throw damagedPDF(
|
||||
("object stream " + std::to_string(obj_stream_number) +
|
||||
" has incorrect keys"));
|
||||
("object stream " + std::to_string(obj_stream_number) + " has incorrect keys"));
|
||||
}
|
||||
|
||||
int n = dict.getKey("/N").getIntValueAsInt();
|
||||
@ -1874,8 +1785,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
|
||||
auto input = std::shared_ptr<InputSource>(
|
||||
// line-break
|
||||
new BufferInputSource(
|
||||
(m->file->getName() + " object stream " +
|
||||
std::to_string(obj_stream_number)),
|
||||
(m->file->getName() + " object stream " + std::to_string(obj_stream_number)),
|
||||
bp.get()));
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
@ -1902,8 +1812,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
|
||||
for (auto const& iter: offsets) {
|
||||
QPDFObjGen og(iter.first, 0);
|
||||
QPDFXRefEntry const& entry = m->xref_table[og];
|
||||
if ((entry.getType() == 2) &&
|
||||
(entry.getObjStreamNumber() == obj_stream_number)) {
|
||||
if ((entry.getType() == 2) && (entry.getObjStreamNumber() == obj_stream_number)) {
|
||||
int offset = iter.second;
|
||||
input->seek(offset, SEEK_SET);
|
||||
QPDFObjectHandle oh = readObject(input, "", og, true);
|
||||
@ -1956,8 +1865,7 @@ QPDF::nextObjGen()
|
||||
{
|
||||
int max_objid = toI(getObjectCount());
|
||||
if (max_objid == std::numeric_limits<int>::max()) {
|
||||
throw std::range_error(
|
||||
"max object id is too high to create new objects");
|
||||
throw std::range_error("max object id is too high to create new objects");
|
||||
}
|
||||
return QPDFObjGen(max_objid + 1, 0);
|
||||
}
|
||||
@ -1974,8 +1882,7 @@ QPDFObjectHandle
|
||||
QPDF::makeIndirectObject(QPDFObjectHandle oh)
|
||||
{
|
||||
if (!oh.isInitialized()) {
|
||||
throw std::logic_error(
|
||||
"attempted to make an uninitialized QPDFObjectHandle indirect");
|
||||
throw std::logic_error("attempted to make an uninitialized QPDFObjectHandle indirect");
|
||||
}
|
||||
return makeIndirectFromQPDFObject(oh.getObj());
|
||||
}
|
||||
@ -1989,16 +1896,15 @@ QPDF::newReserved()
|
||||
QPDFObjectHandle
|
||||
QPDF::newStream()
|
||||
{
|
||||
return makeIndirectFromQPDFObject(QPDF_Stream::create(
|
||||
this, nextObjGen(), QPDFObjectHandle::newDictionary(), 0, 0));
|
||||
return makeIndirectFromQPDFObject(
|
||||
QPDF_Stream::create(this, nextObjGen(), QPDFObjectHandle::newDictionary(), 0, 0));
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDF::newStream(std::shared_ptr<Buffer> data)
|
||||
{
|
||||
auto result = newStream();
|
||||
result.replaceStreamData(
|
||||
data, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
result.replaceStreamData(data, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2006,8 +1912,7 @@ QPDFObjectHandle
|
||||
QPDF::newStream(std::string const& data)
|
||||
{
|
||||
auto result = newStream();
|
||||
result.replaceStreamData(
|
||||
data, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
result.replaceStreamData(data, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2025,8 +1930,7 @@ QPDF::reserveObjectIfNotExists(QPDFObjGen const& og)
|
||||
QPDFObjectHandle
|
||||
QPDF::reserveStream(QPDFObjGen const& og)
|
||||
{
|
||||
return {
|
||||
QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
|
||||
return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
@ -2069,8 +1973,7 @@ QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
|
||||
{
|
||||
if (oh.isIndirect() || !oh.isInitialized()) {
|
||||
QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
|
||||
throw std::logic_error(
|
||||
"QPDF::replaceObject called with indirect object handle");
|
||||
throw std::logic_error("QPDF::replaceObject called with indirect object handle");
|
||||
}
|
||||
updateCache(og, oh.getObj(), -1, -1);
|
||||
}
|
||||
@ -2132,14 +2035,12 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign)
|
||||
// the intention is to not update the pages tree.
|
||||
if (!foreign.isIndirect()) {
|
||||
QTC::TC("qpdf", "QPDF copyForeign direct");
|
||||
throw std::logic_error(
|
||||
"QPDF::copyForeign called with direct object handle");
|
||||
throw std::logic_error("QPDF::copyForeign called with direct object handle");
|
||||
}
|
||||
QPDF& other = foreign.getQPDF();
|
||||
if (&other == this) {
|
||||
QTC::TC("qpdf", "QPDF copyForeign not foreign");
|
||||
throw std::logic_error(
|
||||
"QPDF::copyForeign called with object from this QPDF");
|
||||
throw std::logic_error("QPDF::copyForeign called with object from this QPDF");
|
||||
}
|
||||
|
||||
ObjCopier& obj_copier = m->object_copiers[other.m->unique_id];
|
||||
@ -2163,8 +2064,7 @@ QPDF::copyForeignObject(QPDFObjectHandle foreign)
|
||||
|
||||
// Copy any new objects and replace the reservations.
|
||||
for (auto& to_copy: obj_copier.to_copy) {
|
||||
QPDFObjectHandle copy =
|
||||
replaceForeignIndirectObjects(to_copy, obj_copier, true);
|
||||
QPDFObjectHandle copy = replaceForeignIndirectObjects(to_copy, obj_copier, true);
|
||||
if (!to_copy.isStream()) {
|
||||
QPDFObjGen og(to_copy.getObjGen());
|
||||
replaceReserved(obj_copier.object_map[og], copy);
|
||||
@ -2180,8 +2080,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top)
|
||||
{
|
||||
auto foreign_tc = foreign.getTypeCode();
|
||||
if (foreign_tc == ::ot_reserved) {
|
||||
throw std::logic_error(
|
||||
"QPDF: attempting to copy a foreign reserved object");
|
||||
throw std::logic_error("QPDF: attempting to copy a foreign reserved object");
|
||||
}
|
||||
|
||||
if (foreign.isPagesObject()) {
|
||||
@ -2209,8 +2108,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top)
|
||||
QTC::TC("qpdf", "QPDF copy indirect");
|
||||
if (obj_copier.object_map.count(foreign_og) == 0) {
|
||||
obj_copier.to_copy.push_back(foreign);
|
||||
obj_copier.object_map[foreign_og] =
|
||||
foreign.isStream() ? newStream() : newReserved();
|
||||
obj_copier.object_map[foreign_og] = foreign.isStream() ? newStream() : newReserved();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2234,8 +2132,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top)
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDF::replaceForeignIndirectObjects(
|
||||
QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top)
|
||||
QPDF::replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top)
|
||||
{
|
||||
auto foreign_tc = foreign.getTypeCode();
|
||||
QPDFObjectHandle result;
|
||||
@ -2257,8 +2154,7 @@ QPDF::replaceForeignIndirectObjects(
|
||||
for (int i = 0; i < n; ++i) {
|
||||
result.appendItem(
|
||||
// line-break
|
||||
replaceForeignIndirectObjects(
|
||||
foreign.getArrayItem(i), obj_copier, false));
|
||||
replaceForeignIndirectObjects(foreign.getArrayItem(i), obj_copier, false));
|
||||
}
|
||||
} else if (foreign_tc == ::ot_dictionary) {
|
||||
QTC::TC("qpdf", "QPDF replace dictionary");
|
||||
@ -2266,9 +2162,7 @@ QPDF::replaceForeignIndirectObjects(
|
||||
std::set<std::string> keys = foreign.getKeys();
|
||||
for (auto const& iter: keys) {
|
||||
result.replaceKey(
|
||||
iter,
|
||||
replaceForeignIndirectObjects(
|
||||
foreign.getKey(iter), obj_copier, false));
|
||||
iter, replaceForeignIndirectObjects(foreign.getKey(iter), obj_copier, false));
|
||||
}
|
||||
} else if (foreign_tc == ::ot_stream) {
|
||||
QTC::TC("qpdf", "QPDF replace stream");
|
||||
@ -2279,9 +2173,7 @@ QPDF::replaceForeignIndirectObjects(
|
||||
std::set<std::string> keys = old_dict.getKeys();
|
||||
for (auto const& iter: keys) {
|
||||
dict.replaceKey(
|
||||
iter,
|
||||
replaceForeignIndirectObjects(
|
||||
old_dict.getKey(iter), obj_copier, false));
|
||||
iter, replaceForeignIndirectObjects(old_dict.getKey(iter), obj_copier, false));
|
||||
}
|
||||
copyStreamData(result, foreign);
|
||||
} else {
|
||||
@ -2309,8 +2201,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
|
||||
if (m->copied_stream_data_provider == nullptr) {
|
||||
m->copied_stream_data_provider = new CopiedStreamDataProvider(*this);
|
||||
m->copied_streams =
|
||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider>(
|
||||
m->copied_stream_data_provider);
|
||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider>(m->copied_stream_data_provider);
|
||||
}
|
||||
QPDFObjGen local_og(result.getObjGen());
|
||||
// Copy information from the foreign stream so we can pipe its
|
||||
@ -2325,8 +2216,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
|
||||
" stream object from foreign stream");
|
||||
}
|
||||
std::shared_ptr<Buffer> stream_buffer = stream->getStreamDataBuffer();
|
||||
if ((foreign_stream_qpdf.m->immediate_copy_from) &&
|
||||
(stream_buffer == nullptr)) {
|
||||
if ((foreign_stream_qpdf.m->immediate_copy_from) && (stream_buffer == nullptr)) {
|
||||
// Pull the stream data into a buffer before attempting
|
||||
// the copy operation. Do it on the source stream so that
|
||||
// if the source stream is copied multiple times, we don't
|
||||
@ -2347,12 +2237,9 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
|
||||
} else if (stream_provider.get()) {
|
||||
// In this case, the remote stream's QPDF must stay in scope.
|
||||
QTC::TC("qpdf", "QPDF copy foreign stream with provider");
|
||||
m->copied_stream_data_provider->registerForeignStream(
|
||||
local_og, foreign);
|
||||
m->copied_stream_data_provider->registerForeignStream(local_og, foreign);
|
||||
result.replaceStreamData(
|
||||
m->copied_streams,
|
||||
dict.getKey("/Filter"),
|
||||
dict.getKey("/DecodeParms"));
|
||||
m->copied_streams, dict.getKey("/Filter"), dict.getKey("/DecodeParms"));
|
||||
} else {
|
||||
auto foreign_stream_data = std::make_shared<ForeignStreamData>(
|
||||
foreign_stream_qpdf.m->encp,
|
||||
@ -2361,20 +2248,16 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
|
||||
stream->getParsedOffset(),
|
||||
stream->getLength(),
|
||||
dict);
|
||||
m->copied_stream_data_provider->registerForeignStream(
|
||||
local_og, foreign_stream_data);
|
||||
m->copied_stream_data_provider->registerForeignStream(local_og, foreign_stream_data);
|
||||
result.replaceStreamData(
|
||||
m->copied_streams,
|
||||
dict.getKey("/Filter"),
|
||||
dict.getKey("/DecodeParms"));
|
||||
m->copied_streams, dict.getKey("/Filter"), dict.getKey("/DecodeParms"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
|
||||
{
|
||||
swapObjects(
|
||||
QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2));
|
||||
swapObjects(QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2));
|
||||
}
|
||||
|
||||
void
|
||||
@ -2519,8 +2402,7 @@ QPDF::getCompressibleObjGens()
|
||||
if (og == encryption_dict_og) {
|
||||
QTC::TC("qpdf", "QPDF exclude encryption dictionary");
|
||||
} else if (!(obj.isStream() ||
|
||||
(obj.isDictionaryOfType("/Sig") &&
|
||||
obj.hasKey("/ByteRange") &&
|
||||
(obj.isDictionaryOfType("/Sig") && obj.hasKey("/ByteRange") &&
|
||||
obj.hasKey("/Contents")))) {
|
||||
result.push_back(og);
|
||||
}
|
||||
@ -2571,8 +2453,7 @@ QPDF::pipeStreamData(
|
||||
{
|
||||
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
||||
if (encp->encrypted) {
|
||||
decryptStream(
|
||||
encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete);
|
||||
decryptStream(encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
@ -2584,10 +2465,7 @@ QPDF::pipeStreamData(
|
||||
size_t len = file->read(buf, to_read);
|
||||
if (len == 0) {
|
||||
throw damagedPDF(
|
||||
file,
|
||||
"",
|
||||
file->getLastOffset(),
|
||||
"unexpected EOF reading stream data");
|
||||
file, "", file->getLastOffset(), "unexpected EOF reading stream data");
|
||||
}
|
||||
length -= len;
|
||||
pipeline->write(buf, len);
|
||||
@ -2607,8 +2485,8 @@ QPDF::pipeStreamData(
|
||||
file,
|
||||
"",
|
||||
file->getLastOffset(),
|
||||
("error decoding stream data for object " +
|
||||
og.unparse(' ') + ": " + e.what())));
|
||||
("error decoding stream data for object " + og.unparse(' ') + ": " +
|
||||
e.what())));
|
||||
if (will_retry) {
|
||||
qpdf_for_warning.warn(
|
||||
// line-break
|
||||
@ -2694,17 +2572,14 @@ QPDF::damagedPDF(
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message)
|
||||
{
|
||||
return QPDFExc(
|
||||
qpdf_e_damaged_pdf, input->getName(), object, offset, message);
|
||||
return QPDFExc(qpdf_e_damaged_pdf, input->getName(), object, offset, message);
|
||||
}
|
||||
|
||||
// Return an exception of type qpdf_e_damaged_pdf. The object is taken from
|
||||
// m->last_object_description.
|
||||
QPDFExc
|
||||
QPDF::damagedPDF(
|
||||
std::shared_ptr<InputSource> const& input,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message)
|
||||
std::shared_ptr<InputSource> const& input, qpdf_offset_t offset, std::string const& message)
|
||||
{
|
||||
return damagedPDF(input, m->last_object_description, offset, message);
|
||||
}
|
||||
@ -2712,11 +2587,9 @@ QPDF::damagedPDF(
|
||||
// Return an exception of type qpdf_e_damaged_pdf. The filename is taken from
|
||||
// m->file.
|
||||
QPDFExc
|
||||
QPDF::damagedPDF(
|
||||
std::string const& object, qpdf_offset_t offset, std::string const& message)
|
||||
QPDF::damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message)
|
||||
{
|
||||
return QPDFExc(
|
||||
qpdf_e_damaged_pdf, m->file->getName(), object, offset, message);
|
||||
return QPDFExc(qpdf_e_damaged_pdf, m->file->getName(), object, offset, message);
|
||||
}
|
||||
|
||||
// Return an exception of type qpdf_e_damaged_pdf. The filename is taken from
|
||||
@ -2741,8 +2614,7 @@ QPDF::damagedPDF(qpdf_offset_t offset, std::string const& message)
|
||||
QPDFExc
|
||||
QPDF::damagedPDF(std::string const& message)
|
||||
{
|
||||
return damagedPDF(
|
||||
m->last_object_description, m->file->getLastOffset(), message);
|
||||
return damagedPDF(m->last_object_description, m->file->getLastOffset(), message);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -41,8 +41,7 @@ QPDFAcroFormDocumentHelper::getOrCreateAcroForm()
|
||||
auto acroform = this->qpdf.getRoot().getKey("/AcroForm");
|
||||
if (!acroform.isDictionary()) {
|
||||
acroform = this->qpdf.getRoot().replaceKeyAndGetNew(
|
||||
"/AcroForm",
|
||||
this->qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary()));
|
||||
"/AcroForm", this->qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary()));
|
||||
}
|
||||
return acroform;
|
||||
}
|
||||
@ -53,24 +52,20 @@ QPDFAcroFormDocumentHelper::addFormField(QPDFFormFieldObjectHelper ff)
|
||||
auto acroform = getOrCreateAcroForm();
|
||||
auto fields = acroform.getKey("/Fields");
|
||||
if (!fields.isArray()) {
|
||||
fields = acroform.replaceKeyAndGetNew(
|
||||
"/Fields", QPDFObjectHandle::newArray());
|
||||
fields = acroform.replaceKeyAndGetNew("/Fields", QPDFObjectHandle::newArray());
|
||||
}
|
||||
fields.appendItem(ff.getObjectHandle());
|
||||
QPDFObjGen::set visited;
|
||||
traverseField(
|
||||
ff.getObjectHandle(), QPDFObjectHandle::newNull(), 0, visited);
|
||||
traverseField(ff.getObjectHandle(), QPDFObjectHandle::newNull(), 0, visited);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::addAndRenameFormFields(
|
||||
std::vector<QPDFObjectHandle> fields)
|
||||
QPDFAcroFormDocumentHelper::addAndRenameFormFields(std::vector<QPDFObjectHandle> fields)
|
||||
{
|
||||
analyze();
|
||||
std::map<std::string, std::string> renames;
|
||||
QPDFObjGen::set seen;
|
||||
for (std::list<QPDFObjectHandle> queue{fields.begin(), fields.end()};
|
||||
!queue.empty();
|
||||
for (std::list<QPDFObjectHandle> queue{fields.begin(), fields.end()}; !queue.empty();
|
||||
queue.pop_front()) {
|
||||
auto& obj = queue.front();
|
||||
if (seen.add(obj)) {
|
||||
@ -90,8 +85,7 @@ QPDFAcroFormDocumentHelper::addAndRenameFormFields(
|
||||
// at the end of the fully qualified name, appending to /T
|
||||
// has the effect of appending the same thing to the fully
|
||||
// qualified name.
|
||||
std::string old_name =
|
||||
QPDFFormFieldObjectHelper(obj).getFullyQualifiedName();
|
||||
std::string old_name = QPDFFormFieldObjectHelper(obj).getFullyQualifiedName();
|
||||
if (renames.count(old_name) == 0) {
|
||||
std::string new_name = old_name;
|
||||
int suffix = 0;
|
||||
@ -120,8 +114,7 @@ QPDFAcroFormDocumentHelper::addAndRenameFormFields(
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::removeFormFields(
|
||||
std::set<QPDFObjGen> const& to_remove)
|
||||
QPDFAcroFormDocumentHelper::removeFormFields(std::set<QPDFObjGen> const& to_remove)
|
||||
{
|
||||
auto acroform = this->qpdf.getRoot().getKey("/AcroForm");
|
||||
if (!acroform.isDictionary()) {
|
||||
@ -162,8 +155,7 @@ QPDFAcroFormDocumentHelper::removeFormFields(
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::setFormFieldName(
|
||||
QPDFFormFieldObjectHelper ff, std::string const& name)
|
||||
QPDFAcroFormDocumentHelper::setFormFieldName(QPDFFormFieldObjectHelper ff, std::string const& name)
|
||||
{
|
||||
ff.setFieldAttribute("/T", name);
|
||||
QPDFObjGen::set visited;
|
||||
@ -257,8 +249,7 @@ QPDFAcroFormDocumentHelper::analyze()
|
||||
QPDFObjectHandle fields = acroform.getKey("/Fields");
|
||||
if (!fields.isArray()) {
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper fields not array");
|
||||
acroform.warnIfPossible(
|
||||
"/Fields key of /AcroForm dictionary is not an array; ignoring");
|
||||
acroform.warnIfPossible("/Fields key of /AcroForm dictionary is not an array; ignoring");
|
||||
fields = QPDFObjectHandle::newArray();
|
||||
}
|
||||
|
||||
@ -294,12 +285,10 @@ QPDFAcroFormDocumentHelper::analyze()
|
||||
// adding a self-contained annotation (merged with the
|
||||
// field dictionary) to the page's /Annots array and
|
||||
// forgetting to also put it in /AcroForm.
|
||||
annot.warnIfPossible(
|
||||
"this widget annotation is not"
|
||||
annot.warnIfPossible("this widget annotation is not"
|
||||
" reachable from /AcroForm in the document catalog");
|
||||
m->annotation_to_field[og] = QPDFFormFieldObjectHelper(annot);
|
||||
m->field_to_annotations[og].push_back(
|
||||
QPDFAnnotationObjectHelper(annot));
|
||||
m->field_to_annotations[og].push_back(QPDFAnnotationObjectHelper(annot));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -307,10 +296,7 @@ QPDFAcroFormDocumentHelper::analyze()
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::traverseField(
|
||||
QPDFObjectHandle field,
|
||||
QPDFObjectHandle parent,
|
||||
int depth,
|
||||
QPDFObjGen::set& visited)
|
||||
QPDFObjectHandle field, QPDFObjectHandle parent, int depth, QPDFObjGen::set& visited)
|
||||
{
|
||||
if (depth > 100) {
|
||||
// Arbitrarily cut off recursion at a fixed depth to avoid
|
||||
@ -319,15 +305,13 @@ QPDFAcroFormDocumentHelper::traverseField(
|
||||
}
|
||||
if (!field.isIndirect()) {
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper direct field");
|
||||
field.warnIfPossible(
|
||||
"encountered a direct object as a field or annotation while"
|
||||
field.warnIfPossible("encountered a direct object as a field or annotation while"
|
||||
" traversing /AcroForm; ignoring field or annotation");
|
||||
return;
|
||||
}
|
||||
if (!field.isDictionary()) {
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper non-dictionary field");
|
||||
field.warnIfPossible(
|
||||
"encountered a non-dictionary as a field or annotation while"
|
||||
field.warnIfPossible("encountered a non-dictionary as a field or annotation while"
|
||||
" traversing /AcroForm; ignoring field or annotation");
|
||||
return;
|
||||
}
|
||||
@ -359,23 +343,17 @@ QPDFAcroFormDocumentHelper::traverseField(
|
||||
if (field.hasKey("/Parent")) {
|
||||
is_field = true;
|
||||
}
|
||||
if (field.hasKey("/Subtype") || field.hasKey("/Rect") ||
|
||||
field.hasKey("/AP")) {
|
||||
if (field.hasKey("/Subtype") || field.hasKey("/Rect") || field.hasKey("/AP")) {
|
||||
is_annotation = true;
|
||||
}
|
||||
}
|
||||
|
||||
QTC::TC(
|
||||
"qpdf", "QPDFAcroFormDocumentHelper field found", (depth == 0) ? 0 : 1);
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFAcroFormDocumentHelper annotation found",
|
||||
(is_field ? 0 : 1));
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper field found", (depth == 0) ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper annotation found", (is_field ? 0 : 1));
|
||||
|
||||
if (is_annotation) {
|
||||
QPDFObjectHandle our_field = (is_field ? field : parent);
|
||||
m->field_to_annotations[our_field.getObjGen()].push_back(
|
||||
QPDFAnnotationObjectHelper(field));
|
||||
m->field_to_annotations[our_field.getObjGen()].push_back(QPDFAnnotationObjectHelper(field));
|
||||
m->annotation_to_field[og] = QPDFFormFieldObjectHelper(our_field);
|
||||
}
|
||||
|
||||
@ -400,8 +378,7 @@ QPDFAcroFormDocumentHelper::getNeedAppearances()
|
||||
{
|
||||
bool result = false;
|
||||
QPDFObjectHandle acroform = this->qpdf.getRoot().getKey("/AcroForm");
|
||||
if (acroform.isDictionary() &&
|
||||
acroform.getKey("/NeedAppearances").isBool()) {
|
||||
if (acroform.isDictionary() && acroform.getKey("/NeedAppearances").isBool()) {
|
||||
result = acroform.getKey("/NeedAppearances").getBoolValue();
|
||||
}
|
||||
return result;
|
||||
@ -418,8 +395,7 @@ QPDFAcroFormDocumentHelper::setNeedAppearances(bool val)
|
||||
return;
|
||||
}
|
||||
if (val) {
|
||||
acroform.replaceKey(
|
||||
"/NeedAppearances", QPDFObjectHandle::newBool(true));
|
||||
acroform.replaceKey("/NeedAppearances", QPDFObjectHandle::newBool(true));
|
||||
} else {
|
||||
acroform.removeKey("/NeedAppearances");
|
||||
}
|
||||
@ -472,8 +448,7 @@ QPDFAcroFormDocumentHelper::adjustInheritedFields(
|
||||
// we may be put a value on the field that is unused. This is
|
||||
// harmless, so it's not worth trying to work around.
|
||||
|
||||
auto has_explicit = [](QPDFFormFieldObjectHelper& field,
|
||||
std::string const& key) {
|
||||
auto has_explicit = [](QPDFFormFieldObjectHelper& field, std::string const& key) {
|
||||
if (field.getObjectHandle().hasKey(key)) {
|
||||
return true;
|
||||
}
|
||||
@ -490,16 +465,14 @@ QPDFAcroFormDocumentHelper::adjustInheritedFields(
|
||||
std::string da = cur_field.getDefaultAppearance();
|
||||
if (da != from_default_da) {
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper override da");
|
||||
obj.replaceKey(
|
||||
"/DA", QPDFObjectHandle::newUnicodeString(from_default_da));
|
||||
obj.replaceKey("/DA", QPDFObjectHandle::newUnicodeString(from_default_da));
|
||||
}
|
||||
}
|
||||
if (override_q && (!has_explicit(cur_field, "/Q"))) {
|
||||
int q = cur_field.getQuadding();
|
||||
if (q != from_default_q) {
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper override q");
|
||||
obj.replaceKey(
|
||||
"/Q", QPDFObjectHandle::newInteger(from_default_q));
|
||||
obj.replaceKey("/Q", QPDFObjectHandle::newInteger(from_default_q));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -511,11 +484,8 @@ namespace
|
||||
{
|
||||
public:
|
||||
ResourceReplacer(
|
||||
std::map<std::string, std::map<std::string, std::string>> const&
|
||||
dr_map,
|
||||
std::map<
|
||||
std::string,
|
||||
std::map<std::string, std::set<size_t>>> const& rnames);
|
||||
std::map<std::string, std::map<std::string, std::string>> const& dr_map,
|
||||
std::map<std::string, std::map<std::string, std::set<size_t>>> const& rnames);
|
||||
virtual ~ResourceReplacer() = default;
|
||||
virtual void handleToken(QPDFTokenizer::Token const&) override;
|
||||
|
||||
@ -527,8 +497,7 @@ namespace
|
||||
|
||||
ResourceReplacer::ResourceReplacer(
|
||||
std::map<std::string, std::map<std::string, std::string>> const& dr_map,
|
||||
std::map<std::string, std::map<std::string, std::set<size_t>>> const&
|
||||
rnames) :
|
||||
std::map<std::string, std::map<std::string, std::set<size_t>>> const& rnames) :
|
||||
offset(0)
|
||||
{
|
||||
// We have:
|
||||
@ -564,8 +533,7 @@ ResourceReplacer::handleToken(QPDFTokenizer::Token const& token)
|
||||
{
|
||||
bool wrote = false;
|
||||
if (token.getType() == QPDFTokenizer::tt_name) {
|
||||
std::string name =
|
||||
QPDFObjectHandle::newName(token.getValue()).getName();
|
||||
std::string name = QPDFObjectHandle::newName(token.getValue()).getName();
|
||||
if (to_replace.count(name) && to_replace[name].count(offset)) {
|
||||
QTC::TC("qpdf", "QPDFAcroFormDocumentHelper replaced DA token");
|
||||
write(to_replace[name][offset]);
|
||||
@ -580,8 +548,7 @@ ResourceReplacer::handleToken(QPDFTokenizer::Token const& token)
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::adjustDefaultAppearances(
|
||||
QPDFObjectHandle obj,
|
||||
std::map<std::string, std::map<std::string, std::string>> const& dr_map)
|
||||
QPDFObjectHandle obj, std::map<std::string, std::map<std::string, std::string>> const& dr_map)
|
||||
{
|
||||
// This method is called on a field that has been copied from
|
||||
// another file but whose /DA still refers to resources in the
|
||||
@ -624,8 +591,7 @@ QPDFAcroFormDocumentHelper::adjustDefaultAppearances(
|
||||
// then filter it. We don't attach the stream to anything, so it
|
||||
// will get discarded.
|
||||
ResourceFinder rf;
|
||||
auto da_stream =
|
||||
QPDFObjectHandle::newStream(&this->qpdf, DA.getUTF8Value());
|
||||
auto da_stream = QPDFObjectHandle::newStream(&this->qpdf, DA.getUTF8Value());
|
||||
try {
|
||||
auto nwarnings = this->qpdf.numWarnings();
|
||||
da_stream.parseAsContents(&rf);
|
||||
@ -646,15 +612,13 @@ QPDFAcroFormDocumentHelper::adjustDefaultAppearances(
|
||||
Pl_Buffer buf_pl("filtered DA");
|
||||
da_stream.filterAsContents(&rr, &buf_pl);
|
||||
auto buf = buf_pl.getBufferSharedPointer();
|
||||
std::string new_da(
|
||||
reinterpret_cast<char*>(buf->getBuffer()), buf->getSize());
|
||||
std::string new_da(reinterpret_cast<char*>(buf->getBuffer()), buf->getSize());
|
||||
obj.replaceKey("/DA", QPDFObjectHandle::newString(new_da));
|
||||
}
|
||||
|
||||
void
|
||||
QPDFAcroFormDocumentHelper::adjustAppearanceStream(
|
||||
QPDFObjectHandle stream,
|
||||
std::map<std::string, std::map<std::string, std::string>> dr_map)
|
||||
QPDFObjectHandle stream, std::map<std::string, std::map<std::string, std::string>> dr_map)
|
||||
{
|
||||
// We don't have to modify appearance streams or their resource
|
||||
// dictionaries for them to display properly, but we need to do so
|
||||
@ -740,8 +704,7 @@ QPDFAcroFormDocumentHelper::adjustAppearanceStream(
|
||||
} catch (std::exception& e) {
|
||||
// No way to reproduce in test suite right now since error
|
||||
// conditions are converted to warnings.
|
||||
stream.warnIfPossible(
|
||||
std::string("Unable to parse appearance stream: ") + e.what());
|
||||
stream.warnIfPossible(std::string("Unable to parse appearance stream: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,8 +802,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
||||
}
|
||||
dr.makeResourcesIndirect(this->qpdf);
|
||||
if (!dr.isIndirect()) {
|
||||
dr = acroform.replaceKeyAndGetNew(
|
||||
"/DR", this->qpdf.makeIndirectObject(dr));
|
||||
dr = acroform.replaceKeyAndGetNew("/DR", this->qpdf.makeIndirectObject(dr));
|
||||
}
|
||||
// Merge the other document's /DR, creating a conflict
|
||||
// map. mergeResources checks to make sure both objects
|
||||
@ -969,8 +931,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
||||
obj.replaceKey("/Parent", orig_to_copy[parent_og]);
|
||||
} else {
|
||||
parent.warnIfPossible(
|
||||
"while traversing field " +
|
||||
obj.getObjGen().unparse(',') +
|
||||
"while traversing field " + obj.getObjGen().unparse(',') +
|
||||
", found parent (" + parent_og.unparse(',') +
|
||||
") that had not been seen, indicating likely"
|
||||
" invalid field structure");
|
||||
@ -989,11 +950,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
||||
|
||||
if (override_da || override_q) {
|
||||
adjustInheritedFields(
|
||||
obj,
|
||||
override_da,
|
||||
from_default_da,
|
||||
override_q,
|
||||
from_default_q);
|
||||
obj, override_da, from_default_da, override_q, from_default_q);
|
||||
}
|
||||
if (foreign) {
|
||||
// Lazily initialize our /DR and the conflict map.
|
||||
@ -1013,8 +970,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
||||
obj.replaceKey("/DR", dr);
|
||||
}
|
||||
}
|
||||
if (foreign && obj.getKey("/DA").isString() &&
|
||||
(!dr_map.empty())) {
|
||||
if (foreign && obj.getKey("/DA").isString() && (!dr_map.empty())) {
|
||||
adjustDefaultAppearances(obj, dr_map);
|
||||
}
|
||||
}
|
||||
@ -1060,15 +1016,13 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
||||
if (apdict.isDictionary()) {
|
||||
for (auto& ap: apdict.ditems()) {
|
||||
if (ap.second.isStream()) {
|
||||
streams.push_back(
|
||||
replace_stream(apdict, ap.first, ap.second));
|
||||
streams.push_back(replace_stream(apdict, ap.first, ap.second));
|
||||
} else if (ap.second.isDictionary()) {
|
||||
for (auto& ap2: ap.second.ditems()) {
|
||||
if (ap2.second.isStream()) {
|
||||
streams.push_back(
|
||||
// line-break
|
||||
replace_stream(
|
||||
ap.second, ap2.first, ap2.second));
|
||||
replace_stream(ap.second, ap2.first, ap2.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1096,8 +1050,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
||||
adjustAppearanceStream(stream, dr_map);
|
||||
}
|
||||
}
|
||||
auto rect =
|
||||
cm.transformRectangle(annot.getKey("/Rect").getArrayAsRectangle());
|
||||
auto rect = cm.transformRectangle(annot.getKey("/Rect").getArrayAsRectangle());
|
||||
annot.replaceKey("/Rect", QPDFObjectHandle::newFromRectangle(rect));
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,7 @@ QPDFAnnotationObjectHelper::getFlags()
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFAnnotationObjectHelper::getAppearanceStream(
|
||||
std::string const& which, std::string const& state)
|
||||
QPDFAnnotationObjectHelper::getAppearanceStream(std::string const& which, std::string const& state)
|
||||
{
|
||||
QPDFObjectHandle ap = getAppearanceDictionary();
|
||||
std::string desired_state = state.empty() ? getAppearanceState() : state;
|
||||
@ -80,10 +79,7 @@ QPDFAnnotationObjectHelper::getAppearanceStream(
|
||||
|
||||
std::string
|
||||
QPDFAnnotationObjectHelper::getPageContentForAppearance(
|
||||
std::string const& name,
|
||||
int rotate,
|
||||
int required_flags,
|
||||
int forbidden_flags)
|
||||
std::string const& name, int rotate, int required_flags, int forbidden_flags)
|
||||
{
|
||||
if (!getAppearanceStream("/N").isStream()) {
|
||||
return "";
|
||||
@ -242,9 +238,7 @@ QPDFAnnotationObjectHelper::getPageContentForAppearance(
|
||||
// Compute a matrix to transform the appearance box to the rectangle
|
||||
QPDFMatrix AA;
|
||||
AA.translate(rect.llx, rect.lly);
|
||||
AA.scale(
|
||||
(rect.urx - rect.llx) / (T.urx - T.llx),
|
||||
(rect.ury - rect.lly) / (T.ury - T.lly));
|
||||
AA.scale((rect.urx - rect.llx) / (T.urx - T.llx), (rect.ury - rect.lly) / (T.ury - T.lly));
|
||||
AA.translate(-T.llx, -T.lly);
|
||||
if (do_rotate) {
|
||||
AA.rotatex90(rotate);
|
||||
|
@ -9,8 +9,7 @@
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
QPDFArgParser::Members::Members(
|
||||
int argc, char const* const argv[], char const* progname_env) :
|
||||
QPDFArgParser::Members::Members(int argc, char const* const argv[], char const* progname_env) :
|
||||
|
||||
argc(argc),
|
||||
argv(argv),
|
||||
@ -25,19 +24,15 @@ QPDFArgParser::Members::Members(
|
||||
whoami = QUtil::getWhoami(tmp.get());
|
||||
}
|
||||
|
||||
QPDFArgParser::QPDFArgParser(
|
||||
int argc, char const* const argv[], char const* progname_env) :
|
||||
QPDFArgParser::QPDFArgParser(int argc, char const* const argv[], char const* progname_env) :
|
||||
m(new Members(argc, argv, progname_env))
|
||||
{
|
||||
selectHelpOptionTable();
|
||||
char const* help_choices[] = {"all", nullptr};
|
||||
// More help choices are added dynamically.
|
||||
addChoices(
|
||||
"help", bindParam(&QPDFArgParser::argHelp, this), false, help_choices);
|
||||
addInvalidChoiceHandler(
|
||||
"help", bindParam(&QPDFArgParser::invalidHelpArg, this));
|
||||
addBare(
|
||||
"completion-bash", bindBare(&QPDFArgParser::argCompletionBash, this));
|
||||
addChoices("help", bindParam(&QPDFArgParser::argHelp, this), false, help_choices);
|
||||
addInvalidChoiceHandler("help", bindParam(&QPDFArgParser::invalidHelpArg, this));
|
||||
addBare("completion-bash", bindBare(&QPDFArgParser::argCompletionBash, this));
|
||||
addBare("completion-zsh", bindBare(&QPDFArgParser::argCompletionZsh, this));
|
||||
selectMainOptionTable();
|
||||
}
|
||||
@ -62,22 +57,19 @@ QPDFArgParser::selectOptionTable(std::string const& name)
|
||||
auto t = m->option_tables.find(name);
|
||||
if (t == m->option_tables.end()) {
|
||||
QTC::TC("libtests", "QPDFArgParser select unregistered table");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: selecting unregistered option table " + name);
|
||||
throw std::logic_error("QPDFArgParser: selecting unregistered option table " + name);
|
||||
}
|
||||
m->option_table = &(t->second);
|
||||
m->option_table_name = name;
|
||||
}
|
||||
|
||||
void
|
||||
QPDFArgParser::registerOptionTable(
|
||||
std::string const& name, bare_arg_handler_t end_handler)
|
||||
QPDFArgParser::registerOptionTable(std::string const& name, bare_arg_handler_t end_handler)
|
||||
{
|
||||
if (0 != m->option_tables.count(name)) {
|
||||
QTC::TC("libtests", "QPDFArgParser register registered table");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: registering already registered option table " +
|
||||
name);
|
||||
"QPDFArgParser: registering already registered option table " + name);
|
||||
}
|
||||
m->option_tables[name];
|
||||
selectOptionTable(name);
|
||||
@ -90,8 +82,8 @@ QPDFArgParser::registerArg(std::string const& arg)
|
||||
if (0 != m->option_table->count(arg)) {
|
||||
QTC::TC("libtests", "QPDFArgParser duplicate handler");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: adding a duplicate handler for option " + arg +
|
||||
" in " + m->option_table_name + " option table");
|
||||
"QPDFArgParser: adding a duplicate handler for option " + arg + " in " +
|
||||
m->option_table_name + " option table");
|
||||
}
|
||||
return ((*m->option_table)[arg]);
|
||||
}
|
||||
@ -113,9 +105,7 @@ QPDFArgParser::addBare(std::string const& arg, bare_arg_handler_t handler)
|
||||
|
||||
void
|
||||
QPDFArgParser::addRequiredParameter(
|
||||
std::string const& arg,
|
||||
param_arg_handler_t handler,
|
||||
char const* parameter_name)
|
||||
std::string const& arg, param_arg_handler_t handler, char const* parameter_name)
|
||||
{
|
||||
OptionEntry& oe = registerArg(arg);
|
||||
oe.parameter_needed = true;
|
||||
@ -124,8 +114,7 @@ QPDFArgParser::addRequiredParameter(
|
||||
}
|
||||
|
||||
void
|
||||
QPDFArgParser::addOptionalParameter(
|
||||
std::string const& arg, param_arg_handler_t handler)
|
||||
QPDFArgParser::addOptionalParameter(std::string const& arg, param_arg_handler_t handler)
|
||||
{
|
||||
OptionEntry& oe = registerArg(arg);
|
||||
oe.parameter_needed = false;
|
||||
@ -134,10 +123,7 @@ QPDFArgParser::addOptionalParameter(
|
||||
|
||||
void
|
||||
QPDFArgParser::addChoices(
|
||||
std::string const& arg,
|
||||
param_arg_handler_t handler,
|
||||
bool required,
|
||||
char const** choices)
|
||||
std::string const& arg, param_arg_handler_t handler, bool required, char const** choices)
|
||||
{
|
||||
OptionEntry& oe = registerArg(arg);
|
||||
oe.parameter_needed = required;
|
||||
@ -148,14 +134,12 @@ QPDFArgParser::addChoices(
|
||||
}
|
||||
|
||||
void
|
||||
QPDFArgParser::addInvalidChoiceHandler(
|
||||
std::string const& arg, param_arg_handler_t handler)
|
||||
QPDFArgParser::addInvalidChoiceHandler(std::string const& arg, param_arg_handler_t handler)
|
||||
{
|
||||
auto i = m->option_table->find(arg);
|
||||
if (i == m->option_table->end()) {
|
||||
QTC::TC("libtests", "QPDFArgParser invalid choice handler to unknown");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: attempt to add invalid choice handler"
|
||||
throw std::logic_error("QPDFArgParser: attempt to add invalid choice handler"
|
||||
" to unknown argument");
|
||||
}
|
||||
auto& oe = i->second;
|
||||
@ -195,9 +179,7 @@ QPDFArgParser::completionCommon(bool zsh)
|
||||
std::string appimage;
|
||||
if (QUtil::get_env(m->progname_env.c_str(), &executable)) {
|
||||
progname = executable;
|
||||
} else if (
|
||||
QUtil::get_env("APPDIR", &appdir) &&
|
||||
QUtil::get_env("APPIMAGE", &appimage)) {
|
||||
} else if (QUtil::get_env("APPDIR", &appdir) && QUtil::get_env("APPIMAGE", &appimage)) {
|
||||
// Detect if we're in an AppImage and adjust
|
||||
if ((appdir.length() < strlen(m->argv[0])) &&
|
||||
(strncmp(appdir.c_str(), m->argv[0], appdir.length()) == 0)) {
|
||||
@ -345,8 +327,7 @@ QPDFArgParser::handleBashArguments()
|
||||
}
|
||||
// Explicitly discard any non-space-terminated word. The "current
|
||||
// word" is handled specially.
|
||||
m->bash_argv_ph =
|
||||
QUtil::make_shared_array<char const*>(1 + m->bash_argv.size());
|
||||
m->bash_argv_ph = QUtil::make_shared_array<char const*>(1 + m->bash_argv.size());
|
||||
for (size_t i = 0; i < m->bash_argv.size(); ++i) {
|
||||
m->bash_argv_ph.get()[i] = m->bash_argv.at(i).get();
|
||||
}
|
||||
@ -479,8 +460,7 @@ QPDFArgParser::parseArgs()
|
||||
end_option = true;
|
||||
if (oep == m->option_table->end()) {
|
||||
// This is registered automatically, so this can't happen.
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: -- handler not registered");
|
||||
throw std::logic_error("QPDFArgParser: -- handler not registered");
|
||||
}
|
||||
} else if ((arg[0] == '-') && (strcmp(arg, "-") != 0)) {
|
||||
++arg;
|
||||
@ -531,18 +511,15 @@ QPDFArgParser::parseArgs()
|
||||
QTC::TC("libtests", "QPDFArgParser unrecognized");
|
||||
std::string message = "unrecognized argument " + o_arg;
|
||||
if (m->option_table != &m->main_option_table) {
|
||||
message += " (" + m->option_table_name +
|
||||
" options must be terminated with --)";
|
||||
message += " (" + m->option_table_name + " options must be terminated with --)";
|
||||
}
|
||||
usage(message);
|
||||
}
|
||||
|
||||
OptionEntry& oe = oep->second;
|
||||
if ((oe.parameter_needed && (!have_parameter)) ||
|
||||
((!oe.choices.empty() && have_parameter &&
|
||||
(0 == oe.choices.count(parameter))))) {
|
||||
std::string message =
|
||||
"--" + arg_s + " must be given as --" + arg_s + "=";
|
||||
((!oe.choices.empty() && have_parameter && (0 == oe.choices.count(parameter))))) {
|
||||
std::string message = "--" + arg_s + " must be given as --" + arg_s + "=";
|
||||
if (oe.invalid_choice_handler) {
|
||||
oe.invalid_choice_handler(parameter);
|
||||
// Method should call usage() or exit. Just in case it
|
||||
@ -609,9 +586,7 @@ QPDFArgParser::doFinalChecks()
|
||||
|
||||
void
|
||||
QPDFArgParser::addChoicesToCompletions(
|
||||
option_table_t& option_table,
|
||||
std::string const& option,
|
||||
std::string const& extra_prefix)
|
||||
option_table_t& option_table, std::string const& option, std::string const& extra_prefix)
|
||||
{
|
||||
if (option_table.count(option) != 0) {
|
||||
OptionEntry& oe = option_table[option];
|
||||
@ -648,9 +623,7 @@ QPDFArgParser::addOptionsToCompletions(option_table_t& option_table)
|
||||
|
||||
void
|
||||
QPDFArgParser::insertCompletions(
|
||||
option_table_t& option_table,
|
||||
std::string const& choice_option,
|
||||
std::string const& extra_prefix)
|
||||
option_table_t& option_table, std::string const& choice_option, std::string const& extra_prefix)
|
||||
{
|
||||
if (!choice_option.empty()) {
|
||||
addChoicesToCompletions(option_table, choice_option, extra_prefix);
|
||||
@ -666,21 +639,17 @@ QPDFArgParser::handleCompletion()
|
||||
if (m->completions.empty()) {
|
||||
// Detect --option=... Bash treats the = as a word separator.
|
||||
std::string choice_option;
|
||||
if (m->bash_cur.empty() && (m->bash_prev.length() > 2) &&
|
||||
(m->bash_prev.at(0) == '-') && (m->bash_prev.at(1) == '-') &&
|
||||
(m->bash_line.at(m->bash_line.length() - 1) == '=')) {
|
||||
if (m->bash_cur.empty() && (m->bash_prev.length() > 2) && (m->bash_prev.at(0) == '-') &&
|
||||
(m->bash_prev.at(1) == '-') && (m->bash_line.at(m->bash_line.length() - 1) == '=')) {
|
||||
choice_option = m->bash_prev.substr(2, std::string::npos);
|
||||
} else if (
|
||||
(m->bash_prev == "=") &&
|
||||
(m->bash_line.length() > (m->bash_cur.length() + 1))) {
|
||||
} else if ((m->bash_prev == "=") && (m->bash_line.length() > (m->bash_cur.length() + 1))) {
|
||||
// We're sitting at --option=x. Find previous option.
|
||||
size_t end_mark = m->bash_line.length() - m->bash_cur.length() - 1;
|
||||
char before_cur = m->bash_line.at(end_mark);
|
||||
if (before_cur == '=') {
|
||||
size_t space = m->bash_line.find_last_of(' ', end_mark);
|
||||
if (space != std::string::npos) {
|
||||
std::string candidate =
|
||||
m->bash_line.substr(space + 1, end_mark - space - 1);
|
||||
std::string candidate = m->bash_line.substr(space + 1, end_mark - space - 1);
|
||||
if ((candidate.length() > 2) && (candidate.at(0) == '-') &&
|
||||
(candidate.at(1) == '-')) {
|
||||
choice_option = candidate.substr(2, std::string::npos);
|
||||
@ -695,8 +664,7 @@ QPDFArgParser::handleCompletion()
|
||||
insertCompletions(*m->option_table, choice_option, extra_prefix);
|
||||
if (m->argc == 1) {
|
||||
// Help options are valid only by themselves.
|
||||
insertCompletions(
|
||||
m->help_option_table, choice_option, extra_prefix);
|
||||
insertCompletions(m->help_option_table, choice_option, extra_prefix);
|
||||
}
|
||||
}
|
||||
std::string prefix = extra_prefix + m->bash_cur;
|
||||
@ -716,24 +684,19 @@ QPDFArgParser::addHelpFooter(std::string const& text)
|
||||
|
||||
void
|
||||
QPDFArgParser::addHelpTopic(
|
||||
std::string const& topic,
|
||||
std::string const& short_text,
|
||||
std::string const& long_text)
|
||||
std::string const& topic, std::string const& short_text, std::string const& long_text)
|
||||
{
|
||||
if (topic == "all") {
|
||||
QTC::TC("libtests", "QPDFArgParser add reserved help topic");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: can't register reserved help topic " + topic);
|
||||
throw std::logic_error("QPDFArgParser: can't register reserved help topic " + topic);
|
||||
}
|
||||
if (!((topic.length() > 0) && (topic.at(0) != '-'))) {
|
||||
QTC::TC("libtests", "QPDFArgParser bad topic for help");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: help topics must not start with -");
|
||||
throw std::logic_error("QPDFArgParser: help topics must not start with -");
|
||||
}
|
||||
if (m->help_topics.count(topic)) {
|
||||
QTC::TC("libtests", "QPDFArgParser add existing topic");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: topic " + topic + " has already been added");
|
||||
throw std::logic_error("QPDFArgParser: topic " + topic + " has already been added");
|
||||
}
|
||||
|
||||
m->help_topics[topic] = HelpTopic(short_text, long_text);
|
||||
@ -747,23 +710,20 @@ QPDFArgParser::addOptionHelp(
|
||||
std::string const& short_text,
|
||||
std::string const& long_text)
|
||||
{
|
||||
if (!((option_name.length() > 2) && (option_name.at(0) == '-') &&
|
||||
(option_name.at(1) == '-'))) {
|
||||
if (!((option_name.length() > 2) && (option_name.at(0) == '-') && (option_name.at(1) == '-'))) {
|
||||
QTC::TC("libtests", "QPDFArgParser bad option for help");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: options for help must start with --");
|
||||
throw std::logic_error("QPDFArgParser: options for help must start with --");
|
||||
}
|
||||
if (m->option_help.count(option_name)) {
|
||||
QTC::TC("libtests", "QPDFArgParser duplicate option help");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: option " + option_name + " already has help");
|
||||
throw std::logic_error("QPDFArgParser: option " + option_name + " already has help");
|
||||
}
|
||||
auto ht = m->help_topics.find(topic);
|
||||
if (ht == m->help_topics.end()) {
|
||||
QTC::TC("libtests", "QPDFArgParser add to unknown topic");
|
||||
throw std::logic_error(
|
||||
"QPDFArgParser: unable to add option " + option_name +
|
||||
" to unknown help topic " + topic);
|
||||
"QPDFArgParser: unable to add option " + option_name + " to unknown help topic " +
|
||||
topic);
|
||||
}
|
||||
m->option_help[option_name] = HelpTopic(short_text, long_text);
|
||||
ht->second.options.insert(option_name);
|
||||
@ -773,12 +733,9 @@ QPDFArgParser::addOptionHelp(
|
||||
void
|
||||
QPDFArgParser::getTopHelp(std::ostringstream& msg)
|
||||
{
|
||||
msg << "Run \"" << m->whoami << " --help=topic\" for help on a topic."
|
||||
<< std::endl
|
||||
<< "Run \"" << m->whoami << " --help=--option\" for help on an option."
|
||||
<< std::endl
|
||||
<< "Run \"" << m->whoami << " --help=all\" to see all available help."
|
||||
<< std::endl
|
||||
msg << "Run \"" << m->whoami << " --help=topic\" for help on a topic." << std::endl
|
||||
<< "Run \"" << m->whoami << " --help=--option\" for help on an option." << std::endl
|
||||
<< "Run \"" << m->whoami << " --help=all\" to see all available help." << std::endl
|
||||
<< std::endl
|
||||
<< "Topics:" << std::endl;
|
||||
for (auto const& i: m->help_topics) {
|
||||
@ -794,8 +751,7 @@ QPDFArgParser::getAllHelp(std::ostringstream& msg)
|
||||
for (auto const& i: topics) {
|
||||
auto const& topic = i.first;
|
||||
msg << std::endl
|
||||
<< "== " << topic << " (" << i.second.short_text
|
||||
<< ") ==" << std::endl
|
||||
<< "== " << topic << " (" << i.second.short_text << ") ==" << std::endl
|
||||
<< std::endl;
|
||||
getTopicHelp(topic, i.second, msg);
|
||||
}
|
||||
@ -806,8 +762,7 @@ QPDFArgParser::getAllHelp(std::ostringstream& msg)
|
||||
}
|
||||
|
||||
void
|
||||
QPDFArgParser::getTopicHelp(
|
||||
std::string const& name, HelpTopic const& ht, std::ostringstream& msg)
|
||||
QPDFArgParser::getTopicHelp(std::string const& name, HelpTopic const& ht, std::ostringstream& msg)
|
||||
{
|
||||
if (ht.long_text.empty()) {
|
||||
msg << ht.short_text << std::endl;
|
||||
@ -817,8 +772,7 @@ QPDFArgParser::getTopicHelp(
|
||||
if (!ht.options.empty()) {
|
||||
msg << std::endl << "Related options:" << std::endl;
|
||||
for (auto const& i: ht.options) {
|
||||
msg << " " << i << ": " << m->option_help[i].short_text
|
||||
<< std::endl;
|
||||
msg << " " << i << ": " << m->option_help[i].short_text << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,7 @@ QPDFCryptoProvider::getImpl()
|
||||
{
|
||||
QPDFCryptoProvider& p = getInstance();
|
||||
if (p.m->default_provider.empty()) {
|
||||
throw std::logic_error(
|
||||
"QPDFCryptoProvider::getImpl called with no default provider.");
|
||||
throw std::logic_error("QPDFCryptoProvider::getImpl called with no default provider.");
|
||||
}
|
||||
return p.getImpl_internal(p.m->default_provider);
|
||||
}
|
||||
@ -76,8 +75,7 @@ QPDFCryptoProvider::getImpl_internal(std::string const& name) const
|
||||
auto iter = m->providers.find(name);
|
||||
if (iter == m->providers.end()) {
|
||||
throw std::logic_error(
|
||||
"QPDFCryptoProvider requested unknown implementation \"" + name +
|
||||
"\"");
|
||||
"QPDFCryptoProvider requested unknown implementation \"" + name + "\"");
|
||||
}
|
||||
return m->providers[name]();
|
||||
}
|
||||
|
@ -47,8 +47,7 @@ QPDFCrypto_gnutls::MD5_init()
|
||||
if (code < 0) {
|
||||
this->hash_ctx = nullptr;
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: MD5 error: ") +
|
||||
std::string(gnutls_strerror(code)));
|
||||
std::string("gnutls: MD5 error: ") + std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,26 +77,22 @@ QPDFCrypto_gnutls::RC4_init(unsigned char const* key_data, int key_len)
|
||||
{
|
||||
RC4_finalize();
|
||||
if (key_len == -1) {
|
||||
key_len =
|
||||
QIntC::to_int(strlen(reinterpret_cast<char const*>(key_data)));
|
||||
key_len = QIntC::to_int(strlen(reinterpret_cast<char const*>(key_data)));
|
||||
}
|
||||
gnutls_datum_t key;
|
||||
key.data = const_cast<unsigned char*>(key_data);
|
||||
key.size = QIntC::to_uint(key_len);
|
||||
|
||||
int code = gnutls_cipher_init(
|
||||
&this->cipher_ctx, GNUTLS_CIPHER_ARCFOUR_128, &key, nullptr);
|
||||
int code = gnutls_cipher_init(&this->cipher_ctx, GNUTLS_CIPHER_ARCFOUR_128, &key, nullptr);
|
||||
if (code < 0) {
|
||||
this->cipher_ctx = nullptr;
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: RC4 error: ") +
|
||||
std::string(gnutls_strerror(code)));
|
||||
std::string("gnutls: RC4 error: ") + std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFCrypto_gnutls::RC4_process(
|
||||
unsigned char const* in_data, size_t len, unsigned char* out_data)
|
||||
QPDFCrypto_gnutls::RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data)
|
||||
{
|
||||
gnutls_cipher_encrypt2(this->cipher_ctx, in_data, len, out_data, len);
|
||||
}
|
||||
@ -223,29 +218,19 @@ QPDFCrypto_gnutls::rijndael_init(
|
||||
if (code < 0) {
|
||||
this->cipher_ctx = nullptr;
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: AES error: ") +
|
||||
std::string(gnutls_strerror(code)));
|
||||
std::string("gnutls: AES error: ") + std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFCrypto_gnutls::rijndael_process(
|
||||
unsigned char* in_data, unsigned char* out_data)
|
||||
QPDFCrypto_gnutls::rijndael_process(unsigned char* in_data, unsigned char* out_data)
|
||||
{
|
||||
if (this->encrypt) {
|
||||
gnutls_cipher_encrypt2(
|
||||
this->cipher_ctx,
|
||||
in_data,
|
||||
rijndael_buf_size,
|
||||
out_data,
|
||||
rijndael_buf_size);
|
||||
this->cipher_ctx, in_data, rijndael_buf_size, out_data, rijndael_buf_size);
|
||||
} else {
|
||||
gnutls_cipher_decrypt2(
|
||||
this->cipher_ctx,
|
||||
in_data,
|
||||
rijndael_buf_size,
|
||||
out_data,
|
||||
rijndael_buf_size);
|
||||
this->cipher_ctx, in_data, rijndael_buf_size, out_data, rijndael_buf_size);
|
||||
}
|
||||
|
||||
// Gnutls doesn't support AES in ECB (non-CBC) mode, but the
|
||||
@ -253,14 +238,8 @@ QPDFCrypto_gnutls::rijndael_process(
|
||||
// zeroes each time. We jump through a few hoops here to make this
|
||||
// work.
|
||||
if (!this->cbc_mode) {
|
||||
static unsigned char zeroes[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
rijndael_init(
|
||||
this->encrypt,
|
||||
this->aes_key_data,
|
||||
this->aes_key_len,
|
||||
false,
|
||||
zeroes);
|
||||
static unsigned char zeroes[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
rijndael_init(this->encrypt, this->aes_key_data, this->aes_key_len, false, zeroes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,7 @@ QPDFCrypto_native::RC4_init(unsigned char const* key_data, int key_len)
|
||||
}
|
||||
|
||||
void
|
||||
QPDFCrypto_native::RC4_process(
|
||||
unsigned char const* in_data, size_t len, unsigned char* out_data)
|
||||
QPDFCrypto_native::RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data)
|
||||
{
|
||||
this->rc4->process(in_data, len, out_data);
|
||||
}
|
||||
@ -112,13 +111,12 @@ QPDFCrypto_native::rijndael_init(
|
||||
unsigned char* cbc_block)
|
||||
|
||||
{
|
||||
this->aes_pdf = std::make_shared<AES_PDF_native>(
|
||||
encrypt, key_data, key_len, cbc_mode, cbc_block);
|
||||
this->aes_pdf =
|
||||
std::make_shared<AES_PDF_native>(encrypt, key_data, key_len, cbc_mode, cbc_block);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFCrypto_native::rijndael_process(
|
||||
unsigned char* in_data, unsigned char* out_data)
|
||||
QPDFCrypto_native::rijndael_process(unsigned char* in_data, unsigned char* out_data)
|
||||
{
|
||||
this->aes_pdf->update(in_data, out_data);
|
||||
}
|
||||
|
@ -76,8 +76,7 @@ RC4Loader::~RC4Loader()
|
||||
static void
|
||||
bad_bits(int bits)
|
||||
{
|
||||
throw std::logic_error(
|
||||
std::string("unsupported key length: ") + std::to_string(bits));
|
||||
throw std::logic_error(std::string("unsupported key length: ") + std::to_string(bits));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -208,14 +207,11 @@ QPDFCrypto_openssl::RC4_init(unsigned char const* key_data, int key_len)
|
||||
#endif
|
||||
check_openssl(EVP_CIPHER_CTX_reset(cipher_ctx));
|
||||
if (key_len == -1) {
|
||||
key_len =
|
||||
QIntC::to_int(strlen(reinterpret_cast<const char*>(key_data)));
|
||||
key_len = QIntC::to_int(strlen(reinterpret_cast<const char*>(key_data)));
|
||||
}
|
||||
check_openssl(
|
||||
EVP_EncryptInit_ex(cipher_ctx, rc4, nullptr, nullptr, nullptr));
|
||||
check_openssl(EVP_EncryptInit_ex(cipher_ctx, rc4, nullptr, nullptr, nullptr));
|
||||
check_openssl(EVP_CIPHER_CTX_set_key_length(cipher_ctx, key_len));
|
||||
check_openssl(
|
||||
EVP_EncryptInit_ex(cipher_ctx, nullptr, nullptr, key_data, nullptr));
|
||||
check_openssl(EVP_EncryptInit_ex(cipher_ctx, nullptr, nullptr, key_data, nullptr));
|
||||
}
|
||||
|
||||
void
|
||||
@ -242,23 +238,19 @@ QPDFCrypto_openssl::rijndael_init(
|
||||
check_openssl(EVP_CIPHER_CTX_reset(cipher_ctx));
|
||||
check_openssl(
|
||||
// line-break
|
||||
EVP_CipherInit_ex(
|
||||
cipher_ctx, cipher, nullptr, key_data, cbc_block, encrypt));
|
||||
EVP_CipherInit_ex(cipher_ctx, cipher, nullptr, key_data, cbc_block, encrypt));
|
||||
check_openssl(EVP_CIPHER_CTX_set_padding(cipher_ctx, 0));
|
||||
}
|
||||
|
||||
void
|
||||
QPDFCrypto_openssl::RC4_process(
|
||||
unsigned char const* in_data, size_t len, unsigned char* out_data)
|
||||
QPDFCrypto_openssl::RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data)
|
||||
{
|
||||
int out_len = static_cast<int>(len);
|
||||
check_openssl(
|
||||
EVP_EncryptUpdate(cipher_ctx, out_data, &out_len, in_data, out_len));
|
||||
check_openssl(EVP_EncryptUpdate(cipher_ctx, out_data, &out_len, in_data, out_len));
|
||||
}
|
||||
|
||||
void
|
||||
QPDFCrypto_openssl::rijndael_process(
|
||||
unsigned char* in_data, unsigned char* out_data)
|
||||
QPDFCrypto_openssl::rijndael_process(unsigned char* in_data, unsigned char* out_data)
|
||||
{
|
||||
int len = QPDFCryptoImpl::rijndael_buf_size;
|
||||
check_openssl(EVP_CipherUpdate(cipher_ctx, out_data, &len, in_data, len));
|
||||
|
@ -24,13 +24,12 @@ QPDFEFStreamObjectHelper::getParam(std::string const& pkey)
|
||||
}
|
||||
|
||||
void
|
||||
QPDFEFStreamObjectHelper::setParam(
|
||||
std::string const& pkey, QPDFObjectHandle const& pval)
|
||||
QPDFEFStreamObjectHelper::setParam(std::string const& pkey, QPDFObjectHandle const& pval)
|
||||
{
|
||||
auto params = this->oh.getDict().getKey("/Params");
|
||||
if (!params.isDictionary()) {
|
||||
params = this->oh.getDict().replaceKeyAndGetNew(
|
||||
"/Params", QPDFObjectHandle::newDictionary());
|
||||
params =
|
||||
this->oh.getDict().replaceKeyAndGetNew("/Params", QPDFObjectHandle::newDictionary());
|
||||
}
|
||||
params.replaceKey(pkey, pval);
|
||||
}
|
||||
@ -89,8 +88,7 @@ QPDFEFStreamObjectHelper::getChecksum()
|
||||
}
|
||||
|
||||
QPDFEFStreamObjectHelper
|
||||
QPDFEFStreamObjectHelper::createEFStream(
|
||||
QPDF& qpdf, std::shared_ptr<Buffer> data)
|
||||
QPDFEFStreamObjectHelper::createEFStream(QPDF& qpdf, std::shared_ptr<Buffer> data)
|
||||
{
|
||||
return newFromStream(qpdf.newStream(data));
|
||||
}
|
||||
@ -102,12 +100,10 @@ QPDFEFStreamObjectHelper::createEFStream(QPDF& qpdf, std::string const& data)
|
||||
}
|
||||
|
||||
QPDFEFStreamObjectHelper
|
||||
QPDFEFStreamObjectHelper::createEFStream(
|
||||
QPDF& qpdf, std::function<void(Pipeline*)> provider)
|
||||
QPDFEFStreamObjectHelper::createEFStream(QPDF& qpdf, std::function<void(Pipeline*)> provider)
|
||||
{
|
||||
auto stream = qpdf.newStream();
|
||||
stream.replaceStreamData(
|
||||
provider, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
stream.replaceStreamData(provider, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||
return newFromStream(stream);
|
||||
}
|
||||
|
||||
@ -128,8 +124,7 @@ QPDFEFStreamObjectHelper::setModDate(std::string const& date)
|
||||
QPDFEFStreamObjectHelper&
|
||||
QPDFEFStreamObjectHelper::setSubtype(std::string const& subtype)
|
||||
{
|
||||
this->oh.getDict().replaceKey(
|
||||
"/Subtype", QPDFObjectHandle::newName("/" + subtype));
|
||||
this->oh.getDict().replaceKey("/Subtype", QPDFObjectHandle::newName("/" + subtype));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -137,22 +132,18 @@ QPDFEFStreamObjectHelper
|
||||
QPDFEFStreamObjectHelper::newFromStream(QPDFObjectHandle stream)
|
||||
{
|
||||
QPDFEFStreamObjectHelper result(stream);
|
||||
stream.getDict().replaceKey(
|
||||
"/Type", QPDFObjectHandle::newName("/EmbeddedFile"));
|
||||
stream.getDict().replaceKey("/Type", QPDFObjectHandle::newName("/EmbeddedFile"));
|
||||
Pl_Discard discard;
|
||||
// The PDF spec specifies use of MD5 here and notes that it is not
|
||||
// to be used for security. MD5 is known to be insecure.
|
||||
Pl_MD5 md5("EF md5", &discard);
|
||||
Pl_Count count("EF size", &md5);
|
||||
if (!stream.pipeStreamData(&count, nullptr, 0, qpdf_dl_all)) {
|
||||
stream.warnIfPossible(
|
||||
"unable to get stream data for new embedded file stream");
|
||||
stream.warnIfPossible("unable to get stream data for new embedded file stream");
|
||||
} else {
|
||||
result.setParam("/Size", QPDFObjectHandle::newInteger(count.getCount()));
|
||||
result.setParam(
|
||||
"/Size", QPDFObjectHandle::newInteger(count.getCount()));
|
||||
result.setParam(
|
||||
"/CheckSum",
|
||||
QPDFObjectHandle::newString(QUtil::hex_decode(md5.getHexDigest())));
|
||||
"/CheckSum", QPDFObjectHandle::newString(QUtil::hex_decode(md5.getHexDigest())));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -40,8 +40,7 @@ QPDFEmbeddedFileDocumentHelper::QPDFEmbeddedFileDocumentHelper(QPDF& qpdf) :
|
||||
if (names.isDictionary()) {
|
||||
auto embedded_files = names.getKey("/EmbeddedFiles");
|
||||
if (embedded_files.isDictionary()) {
|
||||
m->embedded_files = std::make_shared<QPDFNameTreeObjectHelper>(
|
||||
embedded_files, qpdf);
|
||||
m->embedded_files = std::make_shared<QPDFNameTreeObjectHelper>(embedded_files, qpdf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,8 +60,7 @@ QPDFEmbeddedFileDocumentHelper::initEmbeddedFiles()
|
||||
auto root = qpdf.getRoot();
|
||||
auto names = root.getKey("/Names");
|
||||
if (!names.isDictionary()) {
|
||||
names = root.replaceKeyAndGetNew(
|
||||
"/Names", QPDFObjectHandle::newDictionary());
|
||||
names = root.replaceKeyAndGetNew("/Names", QPDFObjectHandle::newDictionary());
|
||||
}
|
||||
auto embedded_files = names.getKey("/EmbeddedFiles");
|
||||
if (!embedded_files.isDictionary()) {
|
||||
@ -91,8 +89,7 @@ QPDFEmbeddedFileDocumentHelper::getEmbeddedFiles()
|
||||
std::map<std::string, std::shared_ptr<QPDFFileSpecObjectHelper>> result;
|
||||
if (m->embedded_files) {
|
||||
for (auto const& i: *(m->embedded_files)) {
|
||||
result[i.first] =
|
||||
std::make_shared<QPDFFileSpecObjectHelper>(i.second);
|
||||
result[i.first] = std::make_shared<QPDFFileSpecObjectHelper>(i.second);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -19,8 +19,7 @@ QPDFFileSpecObjectHelper::QPDFFileSpecObjectHelper(QPDFObjectHandle oh) :
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> name_keys = {
|
||||
"/UF", "/F", "/Unix", "/DOS", "/Mac"};
|
||||
static std::vector<std::string> name_keys = {"/UF", "/F", "/Unix", "/DOS", "/Mac"};
|
||||
|
||||
std::string
|
||||
QPDFFileSpecObjectHelper::getDescription()
|
||||
@ -90,8 +89,7 @@ QPDFFileSpecObjectHelper::createFileSpec(
|
||||
return createFileSpec(
|
||||
qpdf,
|
||||
filename,
|
||||
QPDFEFStreamObjectHelper::createEFStream(
|
||||
qpdf, QUtil::file_provider(fullpath)));
|
||||
QPDFEFStreamObjectHelper::createEFStream(qpdf, QUtil::file_provider(fullpath)));
|
||||
}
|
||||
|
||||
QPDFFileSpecObjectHelper
|
||||
|
@ -76,9 +76,7 @@ QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name)
|
||||
node = node.getKey("/Parent");
|
||||
result = node.getKey(name);
|
||||
if (!result.isNull()) {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFFormFieldObjectHelper non-trivial inheritance");
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper non-trivial inheritance");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -87,8 +85,7 @@ QPDFFormFieldObjectHelper::getInheritableFieldValue(std::string const& name)
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(
|
||||
std::string const& name)
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(std::string const& name)
|
||||
{
|
||||
QPDFObjectHandle fv = getInheritableFieldValue(name);
|
||||
std::string result;
|
||||
@ -99,8 +96,7 @@ QPDFFormFieldObjectHelper::getInheritableFieldValueAsString(
|
||||
}
|
||||
|
||||
std::string
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(
|
||||
std::string const& name)
|
||||
QPDFFormFieldObjectHelper::getInheritableFieldValueAsName(std::string const& name)
|
||||
{
|
||||
QPDFObjectHandle fv = getInheritableFieldValue(name);
|
||||
std::string result;
|
||||
@ -125,9 +121,7 @@ QPDFFormFieldObjectHelper::getFullyQualifiedName()
|
||||
while (!node.isNull() && seen.add(node)) {
|
||||
if (node.getKey("/T").isString()) {
|
||||
if (!result.empty()) {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFFormFieldObjectHelper non-trivial qualified name");
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper non-trivial qualified name");
|
||||
result = "." + result;
|
||||
}
|
||||
result = node.getKey("/T").getUTF8Value() + result;
|
||||
@ -210,10 +204,7 @@ QPDFFormFieldObjectHelper::getDefaultAppearance()
|
||||
}
|
||||
std::string result;
|
||||
if (value.isString()) {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFFormFieldObjectHelper DA present",
|
||||
looked_in_acroform ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper DA present", looked_in_acroform ? 0 : 1);
|
||||
result = value.getUTF8Value();
|
||||
}
|
||||
return result;
|
||||
@ -230,10 +221,7 @@ QPDFFormFieldObjectHelper::getQuadding()
|
||||
}
|
||||
int result = 0;
|
||||
if (fv.isInteger()) {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFFormFieldObjectHelper Q present",
|
||||
looked_in_acroform ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present", looked_in_acroform ? 0 : 1);
|
||||
result = QIntC::to_int(fv.getIntValue());
|
||||
}
|
||||
return result;
|
||||
@ -255,25 +243,19 @@ QPDFFormFieldObjectHelper::isText()
|
||||
bool
|
||||
QPDFFormFieldObjectHelper::isCheckbox()
|
||||
{
|
||||
return (
|
||||
(getFieldType() == "/Btn") &&
|
||||
((getFlags() & (ff_btn_radio | ff_btn_pushbutton)) == 0));
|
||||
return ((getFieldType() == "/Btn") && ((getFlags() & (ff_btn_radio | ff_btn_pushbutton)) == 0));
|
||||
}
|
||||
|
||||
bool
|
||||
QPDFFormFieldObjectHelper::isRadioButton()
|
||||
{
|
||||
return (
|
||||
(getFieldType() == "/Btn") &&
|
||||
((getFlags() & ff_btn_radio) == ff_btn_radio));
|
||||
return ((getFieldType() == "/Btn") && ((getFlags() & ff_btn_radio) == ff_btn_radio));
|
||||
}
|
||||
|
||||
bool
|
||||
QPDFFormFieldObjectHelper::isPushbutton()
|
||||
{
|
||||
return (
|
||||
(getFieldType() == "/Btn") &&
|
||||
((getFlags() & ff_btn_pushbutton) == ff_btn_pushbutton));
|
||||
return ((getFieldType() == "/Btn") && ((getFlags() & ff_btn_pushbutton) == ff_btn_pushbutton));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -303,15 +285,13 @@ QPDFFormFieldObjectHelper::getChoices()
|
||||
}
|
||||
|
||||
void
|
||||
QPDFFormFieldObjectHelper::setFieldAttribute(
|
||||
std::string const& key, QPDFObjectHandle value)
|
||||
QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, QPDFObjectHandle value)
|
||||
{
|
||||
this->oh.replaceKey(key, value);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFFormFieldObjectHelper::setFieldAttribute(
|
||||
std::string const& key, std::string const& utf8_value)
|
||||
QPDFFormFieldObjectHelper::setFieldAttribute(std::string const& key, std::string const& utf8_value)
|
||||
{
|
||||
this->oh.replaceKey(key, QPDFObjectHandle::newUnicodeString(utf8_value));
|
||||
}
|
||||
@ -330,41 +310,36 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances)
|
||||
}
|
||||
}
|
||||
if (!okay) {
|
||||
this->oh.warnIfPossible(
|
||||
"ignoring attempt to set a checkbox field to a"
|
||||
this->oh.warnIfPossible("ignoring attempt to set a checkbox field to a"
|
||||
" value of other than /Yes or /Off");
|
||||
}
|
||||
} else if (isRadioButton()) {
|
||||
if (value.isName()) {
|
||||
setRadioButtonValue(value);
|
||||
} else {
|
||||
this->oh.warnIfPossible(
|
||||
"ignoring attempt to set a radio button field to"
|
||||
this->oh.warnIfPossible("ignoring attempt to set a radio button field to"
|
||||
" an object that is not a name");
|
||||
}
|
||||
} else if (isPushbutton()) {
|
||||
this->oh.warnIfPossible(
|
||||
"ignoring attempt set the value of a pushbutton field");
|
||||
this->oh.warnIfPossible("ignoring attempt set the value of a pushbutton field");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (value.isString()) {
|
||||
setFieldAttribute(
|
||||
"/V", QPDFObjectHandle::newUnicodeString(value.getUTF8Value()));
|
||||
setFieldAttribute("/V", QPDFObjectHandle::newUnicodeString(value.getUTF8Value()));
|
||||
} else {
|
||||
setFieldAttribute("/V", value);
|
||||
}
|
||||
if (need_appearances) {
|
||||
QPDF& qpdf = this->oh.getQPDF(
|
||||
"QPDFFormFieldObjectHelper::setV called with need_appearances = "
|
||||
QPDF& qpdf =
|
||||
this->oh.getQPDF("QPDFFormFieldObjectHelper::setV called with need_appearances = "
|
||||
"true on an object that is not associated with an owning QPDF");
|
||||
QPDFAcroFormDocumentHelper(qpdf).setNeedAppearances(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFFormFieldObjectHelper::setV(
|
||||
std::string const& utf8_value, bool need_appearances)
|
||||
QPDFFormFieldObjectHelper::setV(std::string const& utf8_value, bool need_appearances)
|
||||
{
|
||||
setV(QPDFObjectHandle::newUnicodeString(utf8_value), need_appearances);
|
||||
}
|
||||
@ -390,8 +365,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name)
|
||||
if (ph.isRadioButton()) {
|
||||
// This is most likely one of the individual buttons. Try
|
||||
// calling on the parent.
|
||||
QTC::TC(
|
||||
"qpdf", "QPDFFormFieldObjectHelper set parent radio button");
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper set parent radio button");
|
||||
ph.setRadioButtonValue(name);
|
||||
return;
|
||||
}
|
||||
@ -419,9 +393,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name)
|
||||
QPDFObjectHandle grandkid = grandkids.getArrayItem(j);
|
||||
AP = grandkid.getKey("/AP");
|
||||
if (!AP.isNull()) {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFFormFieldObjectHelper radio button grandkid");
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper radio button grandkid");
|
||||
annot = grandkid;
|
||||
break;
|
||||
}
|
||||
@ -432,8 +404,7 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name)
|
||||
}
|
||||
if (!annot.isInitialized()) {
|
||||
QTC::TC("qpdf", "QPDFObjectHandle broken radio button");
|
||||
this->oh.warnIfPossible(
|
||||
"unable to set the value of this radio button");
|
||||
this->oh.warnIfPossible("unable to set the value of this radio button");
|
||||
continue;
|
||||
}
|
||||
if (AP.isDictionary() && AP.getKey("/N").isDictionary() &&
|
||||
@ -465,9 +436,7 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value)
|
||||
QPDFObjectHandle kid = kids.getArrayItem(i);
|
||||
AP = kid.getKey("/AP");
|
||||
if (!AP.isNull()) {
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFFormFieldObjectHelper checkbox kid widget");
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper checkbox kid widget");
|
||||
annot = kid;
|
||||
break;
|
||||
}
|
||||
@ -555,8 +524,7 @@ ValueSetter::handleToken(QPDFTokenizer::Token const& token)
|
||||
break;
|
||||
|
||||
case st_bmc:
|
||||
if ((ttype == QPDFTokenizer::tt_space) ||
|
||||
(ttype == QPDFTokenizer::tt_comment)) {
|
||||
if ((ttype == QPDFTokenizer::tt_space) || (ttype == QPDFTokenizer::tt_comment)) {
|
||||
writeToken(token);
|
||||
} else {
|
||||
state = st_emc;
|
||||
@ -642,9 +610,7 @@ ValueSetter::writeAppearance()
|
||||
}
|
||||
highlight = true;
|
||||
highlight_idx = found_idx - QIntC::to_size(wanted_first);
|
||||
for (size_t i = QIntC::to_size(wanted_first);
|
||||
i <= QIntC::to_size(wanted_last);
|
||||
++i) {
|
||||
for (size_t i = QIntC::to_size(wanted_first); i <= QIntC::to_size(wanted_last); ++i) {
|
||||
lines.push_back(opt.at(i));
|
||||
}
|
||||
} else {
|
||||
@ -661,14 +627,12 @@ ValueSetter::writeAppearance()
|
||||
|
||||
// Write the lines centered vertically, highlighting if needed
|
||||
size_t nlines = lines.size();
|
||||
double dy = bbox.ury -
|
||||
((bbox.ury - bbox.lly - (static_cast<double>(nlines) * tfh)) / 2.0);
|
||||
double dy = bbox.ury - ((bbox.ury - bbox.lly - (static_cast<double>(nlines) * tfh)) / 2.0);
|
||||
if (highlight) {
|
||||
write(
|
||||
"q\n0.85 0.85 0.85 rg\n" + QUtil::double_to_string(bbox.llx) + " " +
|
||||
QUtil::double_to_string(
|
||||
bbox.lly + dy -
|
||||
(tfh * (static_cast<double>(highlight_idx + 1)))) +
|
||||
bbox.lly + dy - (tfh * (static_cast<double>(highlight_idx + 1)))) +
|
||||
" " + QUtil::double_to_string(bbox.urx - bbox.llx) + " " +
|
||||
QUtil::double_to_string(tfh) + " re f\nQ\n");
|
||||
}
|
||||
@ -681,10 +645,8 @@ ValueSetter::writeAppearance()
|
||||
// which doesn't seem really worth the effort.
|
||||
if (i == 0) {
|
||||
write(
|
||||
QUtil::double_to_string(bbox.llx + static_cast<double>(dx)) +
|
||||
" " +
|
||||
QUtil::double_to_string(bbox.lly + static_cast<double>(dy)) +
|
||||
" Td\n");
|
||||
QUtil::double_to_string(bbox.llx + static_cast<double>(dx)) + " " +
|
||||
QUtil::double_to_string(bbox.lly + static_cast<double>(dy)) + " Td\n");
|
||||
} else {
|
||||
write("0 " + QUtil::double_to_string(-tfh) + " Td\n");
|
||||
}
|
||||
@ -794,8 +756,7 @@ TfFinder::getFontName()
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFFormFieldObjectHelper::getFontFromResource(
|
||||
QPDFObjectHandle resources, std::string const& name)
|
||||
QPDFFormFieldObjectHelper::getFontFromResource(QPDFObjectHandle resources, std::string const& name)
|
||||
{
|
||||
QPDFObjectHandle result;
|
||||
if (resources.isDictionary() && resources.getKey("/Font").isDictionary() &&
|
||||
@ -806,40 +767,34 @@ QPDFFormFieldObjectHelper::getFontFromResource(
|
||||
}
|
||||
|
||||
void
|
||||
QPDFFormFieldObjectHelper::generateTextAppearance(
|
||||
QPDFAnnotationObjectHelper& aoh)
|
||||
QPDFFormFieldObjectHelper::generateTextAppearance(QPDFAnnotationObjectHelper& aoh)
|
||||
{
|
||||
QPDFObjectHandle AS = aoh.getAppearanceStream("/N");
|
||||
if (AS.isNull()) {
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper create AS from scratch");
|
||||
QPDFObjectHandle::Rectangle rect = aoh.getRect();
|
||||
QPDFObjectHandle::Rectangle bbox(
|
||||
0, 0, rect.urx - rect.llx, rect.ury - rect.lly);
|
||||
QPDFObjectHandle dict = QPDFObjectHandle::parse(
|
||||
"<< /Resources << /ProcSet [ /PDF /Text ] >>"
|
||||
QPDFObjectHandle::Rectangle bbox(0, 0, rect.urx - rect.llx, rect.ury - rect.lly);
|
||||
QPDFObjectHandle dict =
|
||||
QPDFObjectHandle::parse("<< /Resources << /ProcSet [ /PDF /Text ] >>"
|
||||
" /Type /XObject /Subtype /Form >>");
|
||||
dict.replaceKey("/BBox", QPDFObjectHandle::newFromRectangle(bbox));
|
||||
AS = QPDFObjectHandle::newStream(
|
||||
this->oh.getOwningQPDF(), "/Tx BMC\nEMC\n");
|
||||
AS = QPDFObjectHandle::newStream(this->oh.getOwningQPDF(), "/Tx BMC\nEMC\n");
|
||||
AS.replaceDict(dict);
|
||||
QPDFObjectHandle AP = aoh.getAppearanceDictionary();
|
||||
if (AP.isNull()) {
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper create AP from scratch");
|
||||
aoh.getObjectHandle().replaceKey(
|
||||
"/AP", QPDFObjectHandle::newDictionary());
|
||||
aoh.getObjectHandle().replaceKey("/AP", QPDFObjectHandle::newDictionary());
|
||||
AP = aoh.getAppearanceDictionary();
|
||||
}
|
||||
AP.replaceKey("/N", AS);
|
||||
}
|
||||
if (!AS.isStream()) {
|
||||
aoh.getObjectHandle().warnIfPossible(
|
||||
"unable to get normal appearance stream for update");
|
||||
aoh.getObjectHandle().warnIfPossible("unable to get normal appearance stream for update");
|
||||
return;
|
||||
}
|
||||
QPDFObjectHandle bbox_obj = AS.getDict().getKey("/BBox");
|
||||
if (!bbox_obj.isRectangle()) {
|
||||
aoh.getObjectHandle().warnIfPossible(
|
||||
"unable to get appearance stream bounding box");
|
||||
aoh.getObjectHandle().warnIfPossible("unable to get appearance stream bounding box");
|
||||
return;
|
||||
}
|
||||
QPDFObjectHandle::Rectangle bbox = bbox_obj.getArrayAsRectangle();
|
||||
@ -872,8 +827,7 @@ QPDFFormFieldObjectHelper::generateTextAppearance(
|
||||
if (found_font_in_dr && resources.isDictionary()) {
|
||||
QTC::TC("qpdf", "QPDFFormFieldObjectHelper get font from /DR");
|
||||
if (resources.isIndirect()) {
|
||||
resources = resources.getQPDF().makeIndirectObject(
|
||||
resources.shallowCopy());
|
||||
resources = resources.getQPDF().makeIndirectObject(resources.shallowCopy());
|
||||
AS.getDict().replaceKey("/Resources", resources);
|
||||
}
|
||||
// Use mergeResources to force /Font to be local
|
||||
@ -899,6 +853,5 @@ QPDFFormFieldObjectHelper::generateTextAppearance(
|
||||
|
||||
AS.addTokenFilter(
|
||||
// line-break
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter>(
|
||||
new ValueSetter(DA, V, opt, tf, bbox)));
|
||||
std::shared_ptr<QPDFObjectHandle::TokenFilter>(new ValueSetter(DA, V, opt, tf, bbox)));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,8 +46,7 @@ namespace
|
||||
};
|
||||
} // namespace
|
||||
|
||||
ArgParser::ArgParser(
|
||||
QPDFArgParser& ap, std::shared_ptr<QPDFJob::Config> c_main) :
|
||||
ArgParser::ArgParser(QPDFArgParser& ap, std::shared_ptr<QPDFJob::Config> c_main) :
|
||||
ap(ap),
|
||||
c_main(c_main),
|
||||
pages_password(nullptr),
|
||||
@ -107,8 +106,7 @@ ArgParser::argVersion()
|
||||
auto whoami = this->ap.getProgname();
|
||||
*QPDFLogger::defaultLogger()->getInfo()
|
||||
<< whoami << " version " << QPDF::QPDFVersion() << "\n"
|
||||
<< "Run " << whoami
|
||||
<< " --copyright to see copyright and license information.\n";
|
||||
<< "Run " << whoami << " --copyright to see copyright and license information.\n";
|
||||
}
|
||||
|
||||
void
|
||||
@ -152,8 +150,7 @@ ArgParser::argJsonHelp(std::string const& parameter)
|
||||
if ((version < 1) || (version > JSON::LATEST)) {
|
||||
usage(std::string("unsupported json version ") + parameter);
|
||||
}
|
||||
*QPDFLogger::defaultLogger()->getInfo()
|
||||
<< QPDFJob::json_out_schema(version) << "\n";
|
||||
*QPDFLogger::defaultLogger()->getInfo() << QPDFJob::json_out_schema(version) << "\n";
|
||||
}
|
||||
|
||||
void
|
||||
@ -263,10 +260,7 @@ ArgParser::argPagesPositional(std::string const& arg)
|
||||
if (range_p == nullptr) {
|
||||
if (arg.empty()) {
|
||||
// The filename or password was the last argument
|
||||
QTC::TC(
|
||||
"qpdf",
|
||||
"QPDFJob pages range omitted at end",
|
||||
this->pages_password ? 0 : 1);
|
||||
QTC::TC("qpdf", "QPDFJob pages range omitted at end", this->pages_password ? 0 : 1);
|
||||
} else {
|
||||
// We need to accumulate some more arguments
|
||||
return;
|
||||
|
@ -658,8 +658,7 @@ QPDFJob::Config::passwordFile(std::string const& parameter)
|
||||
|
||||
if (lines.size() > 1) {
|
||||
*QPDFLogger::defaultLogger()->getError()
|
||||
<< this->o.m->message_prefix
|
||||
<< ": WARNING: all but the first line of"
|
||||
<< this->o.m->message_prefix << ": WARNING: all but the first line of"
|
||||
<< " the password file are ignored\n";
|
||||
}
|
||||
}
|
||||
@ -751,8 +750,7 @@ QPDFJob::Config::removeUnreferencedResources(std::string const& parameter)
|
||||
QPDFJob::Config*
|
||||
QPDFJob::Config::showObject(std::string const& parameter)
|
||||
{
|
||||
QPDFJob::parse_object_id(
|
||||
parameter, o.m->show_trailer, o.m->show_obj, o.m->show_gen);
|
||||
QPDFJob::parse_object_id(parameter, o.m->show_trailer, o.m->show_obj, o.m->show_gen);
|
||||
o.m->require_outfile = false;
|
||||
return this;
|
||||
}
|
||||
@ -761,13 +759,11 @@ QPDFJob::Config*
|
||||
QPDFJob::Config::jobJsonFile(std::string const& parameter)
|
||||
{
|
||||
try {
|
||||
o.initializeFromJson(
|
||||
QUtil::read_file_into_string(parameter.c_str()), true);
|
||||
o.initializeFromJson(QUtil::read_file_into_string(parameter.c_str()), true);
|
||||
} catch (std::exception& e) {
|
||||
throw std::runtime_error(
|
||||
"error with job-json file " + std::string(parameter) + ": " +
|
||||
e.what() + "\nRun " + this->o.m->message_prefix +
|
||||
" --job-json-help for information on the file format.");
|
||||
"error with job-json file " + std::string(parameter) + ": " + e.what() + "\nRun " +
|
||||
this->o.m->message_prefix + " --job-json-help for information on the file format.");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@ -900,8 +896,7 @@ QPDFJob::AttConfig::replace()
|
||||
QPDFJob::Config*
|
||||
QPDFJob::AttConfig::endAddAttachment()
|
||||
{
|
||||
static std::string now =
|
||||
QUtil::qpdf_time_to_pdf_time(QUtil::get_current_qpdf_time());
|
||||
static std::string now = QUtil::qpdf_time_to_pdf_time(QUtil::get_current_qpdf_time());
|
||||
if (this->att.path.empty()) {
|
||||
usage("add attachment: no file specified");
|
||||
}
|
||||
@ -953,8 +948,7 @@ QPDFJob::PagesConfig*
|
||||
QPDFJob::PagesConfig::pageSpec(
|
||||
std::string const& filename, std::string const& range, char const* password)
|
||||
{
|
||||
this->config->o.m->page_specs.push_back(
|
||||
QPDFJob::PageSpec(filename, password, range));
|
||||
this->config->o.m->page_specs.push_back(QPDFJob::PageSpec(filename, password, range));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1035,9 +1029,7 @@ QPDFJob::UOConfig::password(std::string const& parameter)
|
||||
|
||||
std::shared_ptr<QPDFJob::EncConfig>
|
||||
QPDFJob::Config::encrypt(
|
||||
int keylen,
|
||||
std::string const& user_password,
|
||||
std::string const& owner_password)
|
||||
int keylen, std::string const& user_password, std::string const& owner_password)
|
||||
{
|
||||
o.m->keylen = keylen;
|
||||
if (keylen == 256) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user