mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 02:49:00 +00:00
WHITESPACE ONLY -- expand tabs in source code
This comment expands all tabs using an 8-character tab-width. You should ignore this commit when using git blame or use git blame -w. In the early days, I used to use tabs where possible for indentation, since emacs did this automatically. In recent years, I have switched to only using spaces, which means qpdf source code has been a mixture of spaces and tabs. I have avoided cleaning this up because of not wanting gratuitous whitespaces change to cloud the output of git blame, but I changed my mind after discussing with users who view qpdf source code in editors/IDEs that have other tab widths by default and in light of the fact that I am planning to start applying automatic code formatting soon.
This commit is contained in:
parent
716381f65a
commit
cb769c62e5
@ -150,7 +150,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
char const* infilename = 0;
|
||||
@ -216,9 +216,9 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " exception: "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << " exception: "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -20,16 +20,16 @@ static std::map<QPDFObjGen, int> page_map;
|
||||
void usage()
|
||||
{
|
||||
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
|
||||
<< " --show-targets show target if possible"
|
||||
<< std::endl;
|
||||
<< 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
|
||||
<< " --show-targets show target if possible"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -37,14 +37,14 @@ void print_lines(std::vector<int>& numbers)
|
||||
{
|
||||
for (unsigned int i = 0; i < numbers.size() - 1; ++i)
|
||||
{
|
||||
if (numbers.at(i))
|
||||
{
|
||||
std::cout << "| ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " ";
|
||||
}
|
||||
if (numbers.at(i))
|
||||
{
|
||||
std::cout << "| ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,10 +54,10 @@ void generate_page_map(QPDF& qpdf)
|
||||
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
|
||||
int n = 0;
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFObjectHandle oh = (*iter).getObjectHandle();
|
||||
page_map[oh.getObjGen()] = ++n;
|
||||
QPDFObjectHandle oh = (*iter).getObjectHandle();
|
||||
page_map[oh.getObjGen()] = ++n;
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,50 +163,50 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
|
||||
{
|
||||
std::cout << whoami << " version 1.5" << std::endl;
|
||||
exit(0);
|
||||
std::cout << whoami << " version 1.5" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int arg;
|
||||
for (arg = 1; arg < argc; ++arg)
|
||||
{
|
||||
if (argv[arg][0] == '-')
|
||||
{
|
||||
if (strcmp(argv[arg], "--numbers") == 0)
|
||||
{
|
||||
style = st_numbers;
|
||||
}
|
||||
else if (strcmp(argv[arg], "--lines") == 0)
|
||||
{
|
||||
style = st_lines;
|
||||
}
|
||||
else if (strcmp(argv[arg], "--show-open") == 0)
|
||||
{
|
||||
show_open = true;
|
||||
}
|
||||
else if (strcmp(argv[arg], "--show-targets") == 0)
|
||||
{
|
||||
show_targets = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (argv[arg][0] == '-')
|
||||
{
|
||||
if (strcmp(argv[arg], "--numbers") == 0)
|
||||
{
|
||||
style = st_numbers;
|
||||
}
|
||||
else if (strcmp(argv[arg], "--lines") == 0)
|
||||
{
|
||||
style = st_lines;
|
||||
}
|
||||
else if (strcmp(argv[arg], "--show-open") == 0)
|
||||
{
|
||||
show_open = true;
|
||||
}
|
||||
else if (strcmp(argv[arg], "--show-targets") == 0)
|
||||
{
|
||||
show_targets = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg >= argc)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* filename = argv[arg++];
|
||||
@ -214,38 +214,38 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (arg < argc)
|
||||
{
|
||||
password = argv[arg++];
|
||||
password = argv[arg++];
|
||||
}
|
||||
if (arg != argc)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(filename, password);
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(filename, password);
|
||||
|
||||
QPDFOutlineDocumentHelper odh(qpdf);
|
||||
if (odh.hasOutlines())
|
||||
{
|
||||
std::vector<int> numbers;
|
||||
if (show_targets)
|
||||
{
|
||||
generate_page_map(qpdf);
|
||||
}
|
||||
extract_bookmarks(odh.getTopLevelOutlines(), numbers);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << filename << " has no bookmarks" << std::endl;
|
||||
}
|
||||
if (odh.hasOutlines())
|
||||
{
|
||||
std::vector<int> numbers;
|
||||
if (show_targets)
|
||||
{
|
||||
generate_page_map(qpdf);
|
||||
}
|
||||
extract_bookmarks(odh.getTopLevelOutlines(), numbers);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << filename << " has no bookmarks" << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << filename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << " processing file " << filename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -58,20 +58,20 @@ int main(int argc, char* argv[])
|
||||
|
||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
whoami = p + 1;
|
||||
}
|
||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
whoami = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
whoami = argv[0];
|
||||
whoami = argv[0];
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
infile = argv[1];
|
||||
@ -80,34 +80,34 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
||||
modify_file(qpdf) &&
|
||||
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0))
|
||||
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0))
|
||||
{
|
||||
/* Use static ID for testing only. For production, a
|
||||
* non-static ID is used. See also
|
||||
* qpdf_set_deterministic_ID. */
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
||||
qpdf_write(qpdf);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
||||
qpdf_write(qpdf);
|
||||
}
|
||||
while (qpdf_more_warnings(qpdf))
|
||||
{
|
||||
warnings = 1;
|
||||
printf("warning: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
warnings = 1;
|
||||
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)));
|
||||
errors = 1;
|
||||
printf("error: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
}
|
||||
qpdf_cleanup(&qpdf);
|
||||
if (errors)
|
||||
{
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
else if (warnings)
|
||||
{
|
||||
return 3;
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -20,7 +20,7 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile" << std::endl
|
||||
<< "Applies token filters to infile"
|
||||
<< "Applies token filters to infile"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
@ -78,19 +78,19 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
char const* infilename = argv[1];
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(infilename);
|
||||
QPDF pdf;
|
||||
pdf.processFile(infilename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
int pageno = 0;
|
||||
@ -123,8 +123,8 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -31,7 +31,7 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
||||
std::string const& filter);
|
||||
virtual ~ImageProvider();
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline);
|
||||
Pipeline* pipeline);
|
||||
size_t getWidth() const;
|
||||
size_t getHeight() const;
|
||||
|
||||
@ -142,7 +142,7 @@ ImageProvider::provideStreamData(int objid, int generation,
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " filename" << std::endl
|
||||
<< "Creates a simple PDF and writes it to filename" << std::endl;
|
||||
<< "Creates a simple PDF and writes it to filename" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -424,22 +424,22 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
char const* filename = argv[1];
|
||||
|
||||
try
|
||||
{
|
||||
create_pdf(filename);
|
||||
create_pdf(filename);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -207,7 +207,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
|
||||
StreamReplacer(QPDF* pdf);
|
||||
virtual ~StreamReplacer() = default;
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline) override;
|
||||
Pipeline* pipeline) override;
|
||||
|
||||
void registerStream(
|
||||
QPDFObjectHandle stream,
|
||||
@ -473,7 +473,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
char const* infilename = 0;
|
||||
@ -517,7 +517,7 @@ int main(int argc, char* argv[])
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << ": exception: " << e.what() << std::endl;
|
||||
exit(2);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -13,9 +13,9 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
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;
|
||||
<< std::endl
|
||||
<< "Double size of all pages in infile.pdf;"
|
||||
<< " write output to outfile.pdf" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -26,18 +26,18 @@ static void doubleBoxSize(QPDFObjectHandle& page, char const* box_name)
|
||||
QPDFObjectHandle box = page.getKey(box_name);
|
||||
if (box.isNull())
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (! (box.isArray() && (box.getArrayNItems() == 4)))
|
||||
{
|
||||
throw std::runtime_error(std::string("box ") + box_name +
|
||||
" is not an array of four elements");
|
||||
throw std::runtime_error(std::string("box ") + box_name +
|
||||
" is not an array of four elements");
|
||||
}
|
||||
std::vector<QPDFObjectHandle> doubled;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
doubled.push_back(
|
||||
QPDFObjectHandle::newReal(
|
||||
doubled.push_back(
|
||||
QPDFObjectHandle::newReal(
|
||||
box.getArrayItem(i).getNumericValue() * 2.0, 2));
|
||||
}
|
||||
page.replaceKey(box_name, QPDFObjectHandle::newArray(doubled));
|
||||
@ -50,7 +50,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
// For test suite
|
||||
@ -64,7 +64,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (! ((argc == 3) || (argc == 4)))
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* infilename = argv[1];
|
||||
@ -76,48 +76,48 @@ int main(int argc, char* argv[])
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename, password);
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename, password);
|
||||
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(qpdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter =
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter =
|
||||
pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& ph(*iter);
|
||||
QPDFObjectHandle page = ph.getObjectHandle();
|
||||
QPDFObjectHandle page = ph.getObjectHandle();
|
||||
|
||||
// Prepend the buffer to the page's contents
|
||||
ph.addPageContents(
|
||||
// Prepend the buffer to the page's contents
|
||||
ph.addPageContents(
|
||||
QPDFObjectHandle::newStream(&qpdf, content), true);
|
||||
|
||||
// Double the size of each of the content boxes
|
||||
doubleBoxSize(page, "/MediaBox");
|
||||
doubleBoxSize(page, "/CropBox");
|
||||
doubleBoxSize(page, "/BleedBox");
|
||||
doubleBoxSize(page, "/TrimBox");
|
||||
doubleBoxSize(page, "/ArtBox");
|
||||
}
|
||||
// Double the size of each of the content boxes
|
||||
doubleBoxSize(page, "/MediaBox");
|
||||
doubleBoxSize(page, "/CropBox");
|
||||
doubleBoxSize(page, "/BleedBox");
|
||||
doubleBoxSize(page, "/TrimBox");
|
||||
doubleBoxSize(page, "/ArtBox");
|
||||
}
|
||||
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
w.setStaticID(true); // for testing only
|
||||
w.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
w.setStaticID(true); // for testing only
|
||||
w.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -23,7 +23,7 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile outfile" << std::endl
|
||||
<< "Applies token filters to infile and writes outfile"
|
||||
<< "Applies token filters to infile and writes outfile"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
@ -195,20 +195,20 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
char const* infilename = argv[1];
|
||||
char const* outfilename = argv[2];
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(infilename);
|
||||
QPDF pdf;
|
||||
pdf.processFile(infilename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
@ -233,8 +233,8 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -14,9 +14,9 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
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;
|
||||
<< std::endl
|
||||
<< "Invert some images in infile.pdf;"
|
||||
<< " write output to outfile.pdf" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
|
||||
{
|
||||
}
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline) override;
|
||||
Pipeline* pipeline) override;
|
||||
|
||||
void registerImage(
|
||||
QPDFObjectHandle image,
|
||||
@ -80,13 +80,13 @@ ImageInverter::registerImage(
|
||||
// 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());
|
||||
QPDFObjectHandle::newNull(),
|
||||
QPDFObjectHandle::newNull());
|
||||
}
|
||||
|
||||
void
|
||||
ImageInverter::provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline)
|
||||
Pipeline* pipeline)
|
||||
{
|
||||
// Use the object and generation number supplied to look up the
|
||||
// image data. Then invert the image data and write the inverted
|
||||
@ -99,8 +99,8 @@ ImageInverter::provideStreamData(int objid, int generation,
|
||||
unsigned char ch;
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
ch = QIntC::to_uchar(0xff - buf[i]);
|
||||
pipeline->write(&ch, 1);
|
||||
ch = QIntC::to_uchar(0xff - buf[i]);
|
||||
pipeline->write(&ch, 1);
|
||||
}
|
||||
pipeline->finish();
|
||||
}
|
||||
@ -112,7 +112,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
// For test suite
|
||||
@ -126,7 +126,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (! ((argc == 3) || (argc == 4)))
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* infilename = argv[1];
|
||||
@ -135,64 +135,64 @@ int main(int argc, char* argv[])
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename, password);
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename, password);
|
||||
|
||||
ImageInverter* inv = new ImageInverter;
|
||||
auto p = PointerHolder<QPDFObjectHandle::StreamDataProvider>(inv);
|
||||
ImageInverter* inv = new ImageInverter;
|
||||
auto p = PointerHolder<QPDFObjectHandle::StreamDataProvider>(inv);
|
||||
|
||||
// For each page...
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
// For each page...
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(qpdf).getAllPages();
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& page(*iter);
|
||||
// Get all images on the page.
|
||||
std::map<std::string, QPDFObjectHandle> images =
|
||||
page.getImages();
|
||||
for (auto& iter2: images)
|
||||
{
|
||||
QPDFObjectHandle& image = iter2.second;
|
||||
QPDFObjectHandle image_dict = image.getDict();
|
||||
QPDFObjectHandle color_space =
|
||||
image_dict.getKey("/ColorSpace");
|
||||
QPDFObjectHandle bits_per_component =
|
||||
image_dict.getKey("/BitsPerComponent");
|
||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||
iter != pages.end(); ++iter)
|
||||
{
|
||||
QPDFPageObjectHelper& page(*iter);
|
||||
// Get all images on the page.
|
||||
std::map<std::string, QPDFObjectHandle> images =
|
||||
page.getImages();
|
||||
for (auto& iter2: images)
|
||||
{
|
||||
QPDFObjectHandle& image = iter2.second;
|
||||
QPDFObjectHandle image_dict = image.getDict();
|
||||
QPDFObjectHandle color_space =
|
||||
image_dict.getKey("/ColorSpace");
|
||||
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(0, qpdf_ef_compress,
|
||||
// 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(0, qpdf_ef_compress,
|
||||
qpdf_dl_all) &&
|
||||
color_space.isNameAndEquals("/DeviceGray") &&
|
||||
bits_per_component.isInteger() &&
|
||||
(bits_per_component.getIntValue() == 8))
|
||||
{
|
||||
bits_per_component.isInteger() &&
|
||||
(bits_per_component.getIntValue() == 8))
|
||||
{
|
||||
inv->registerImage(image, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
w.setStaticID(true); // for testing only
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
w.setStaticID(true); // for testing only
|
||||
}
|
||||
w.write();
|
||||
std::cout << whoami << ": new file written to " << outfilename
|
||||
<< std::endl;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -32,20 +32,20 @@ int main(int argc, char* argv[])
|
||||
|
||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
whoami = p + 1;
|
||||
}
|
||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
whoami = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
whoami = argv[0];
|
||||
whoami = argv[0];
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
infile = argv[1];
|
||||
@ -53,36 +53,36 @@ int main(int argc, char* argv[])
|
||||
outfile = argv[3];
|
||||
|
||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
||||
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0))
|
||||
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0))
|
||||
{
|
||||
/* Use static ID for testing only. For production, a
|
||||
* non-static ID is used. See also
|
||||
* qpdf_set_deterministic_ID. */
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
||||
qpdf_set_linearization(qpdf, QPDF_TRUE);
|
||||
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
||||
qpdf_set_linearization(qpdf, QPDF_TRUE);
|
||||
qpdf_register_progress_reporter(qpdf, write_progress, infile);
|
||||
qpdf_write(qpdf);
|
||||
qpdf_write(qpdf);
|
||||
}
|
||||
while (qpdf_more_warnings(qpdf))
|
||||
{
|
||||
warnings = 1;
|
||||
printf("warning: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||
warnings = 1;
|
||||
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)));
|
||||
errors = 1;
|
||||
printf("error: %s\n",
|
||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||
}
|
||||
qpdf_cleanup(&qpdf);
|
||||
if (errors)
|
||||
{
|
||||
return 2;
|
||||
return 2;
|
||||
}
|
||||
else if (warnings)
|
||||
{
|
||||
return 3;
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -16,39 +16,39 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
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"
|
||||
<< "dumps all /Info entries to stdout\n";
|
||||
<< "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"
|
||||
<< "dumps all /Info entries to stdout\n";
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void dumpInfoDict(QPDF& pdf,
|
||||
std::ostream& os = std::cout,
|
||||
std::string const& sep = ":\t")
|
||||
std::ostream& os = std::cout,
|
||||
std::string const& sep = ":\t")
|
||||
{
|
||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||
if (trailer.hasKey("/Info"))
|
||||
{
|
||||
for (auto& it: trailer.getKey("/Info").ditems())
|
||||
{
|
||||
std::string val;
|
||||
if (it.second.isString())
|
||||
{
|
||||
val = it.second.getStringValue();
|
||||
}
|
||||
else if (it.second.isName())
|
||||
{
|
||||
val = it.second.getName();
|
||||
}
|
||||
else // according to PDF Spec 1.5, shouldn't happen
|
||||
{
|
||||
val = it.second.unparseResolved();
|
||||
}
|
||||
os << it.first.substr(1) << sep << val << std::endl; // skip '/'
|
||||
}
|
||||
for (auto& it: trailer.getKey("/Info").ditems())
|
||||
{
|
||||
std::string val;
|
||||
if (it.second.isString())
|
||||
{
|
||||
val = it.second.getStringValue();
|
||||
}
|
||||
else if (it.second.isName())
|
||||
{
|
||||
val = it.second.getName();
|
||||
}
|
||||
else // according to PDF Spec 1.5, shouldn't happen
|
||||
{
|
||||
val = it.second.unparseResolved();
|
||||
}
|
||||
os << it.first.substr(1) << sep << val << std::endl; // skip '/'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,14 +56,14 @@ void pdfDumpInfoDict(char const* fname)
|
||||
{
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(fname);
|
||||
dumpInfoDict(pdf);
|
||||
QPDF pdf;
|
||||
pdf.processFile(fname);
|
||||
dumpInfoDict(pdf);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,19 +78,19 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if ((argc == 2) && (! strcmp(argv[1], "--version")) )
|
||||
{
|
||||
std::cout << whoami << " version " << version << std::endl;
|
||||
exit(0);
|
||||
std::cout << whoami << " version " << version << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
if ((argc == 3) && (! strcmp(argv[1], "--dump")))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info --dump");
|
||||
pdfDumpInfoDict(argv[2]);
|
||||
exit(0);
|
||||
QTC::TC("examples", "pdf-mod-info --dump");
|
||||
pdfDumpInfoDict(argv[2]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
char* fl_in = 0;
|
||||
@ -99,59 +99,59 @@ int main(int argc, char* argv[])
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if ((! strcmp(argv[i], "--in")) && (++i < argc))
|
||||
{
|
||||
fl_in = argv[i];
|
||||
}
|
||||
else if ((! strcmp(argv[i], "--out")) && (++i < argc))
|
||||
{
|
||||
fl_out = argv[i];
|
||||
}
|
||||
else if (! strcmp(argv[i], "--static-id")) // don't document
|
||||
{
|
||||
static_id = true; // this should be used in test suites only
|
||||
}
|
||||
else if ((! strcmp(argv[i], "--key")) && (++i < argc))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info -key");
|
||||
cur_key = argv[i];
|
||||
if (! ((cur_key.length() > 0) && (cur_key.at(0) == '/')))
|
||||
{
|
||||
cur_key = "/" + cur_key;
|
||||
}
|
||||
Keys[cur_key] = "";
|
||||
}
|
||||
else if ((! strcmp(argv[i], "--val")) && (++i < argc))
|
||||
{
|
||||
if (cur_key.empty())
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info usage wrong val");
|
||||
usage();
|
||||
}
|
||||
QTC::TC("examples", "pdf-mod-info -val");
|
||||
Keys[cur_key] = argv[i];
|
||||
cur_key.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info usage junk");
|
||||
usage();
|
||||
}
|
||||
if ((! strcmp(argv[i], "--in")) && (++i < argc))
|
||||
{
|
||||
fl_in = argv[i];
|
||||
}
|
||||
else if ((! strcmp(argv[i], "--out")) && (++i < argc))
|
||||
{
|
||||
fl_out = argv[i];
|
||||
}
|
||||
else if (! strcmp(argv[i], "--static-id")) // don't document
|
||||
{
|
||||
static_id = true; // this should be used in test suites only
|
||||
}
|
||||
else if ((! strcmp(argv[i], "--key")) && (++i < argc))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info -key");
|
||||
cur_key = argv[i];
|
||||
if (! ((cur_key.length() > 0) && (cur_key.at(0) == '/')))
|
||||
{
|
||||
cur_key = "/" + cur_key;
|
||||
}
|
||||
Keys[cur_key] = "";
|
||||
}
|
||||
else if ((! strcmp(argv[i], "--val")) && (++i < argc))
|
||||
{
|
||||
if (cur_key.empty())
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info usage wrong val");
|
||||
usage();
|
||||
}
|
||||
QTC::TC("examples", "pdf-mod-info -val");
|
||||
Keys[cur_key] = argv[i];
|
||||
cur_key.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info usage junk");
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if (! fl_in)
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info no in file");
|
||||
usage();
|
||||
QTC::TC("examples", "pdf-mod-info no in file");
|
||||
usage();
|
||||
}
|
||||
if (! fl_out)
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info in-place");
|
||||
fl_out = fl_in;
|
||||
QTC::TC("examples", "pdf-mod-info in-place");
|
||||
fl_out = fl_in;
|
||||
}
|
||||
if (Keys.size() == 0)
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info no keys");
|
||||
usage();
|
||||
QTC::TC("examples", "pdf-mod-info no keys");
|
||||
usage();
|
||||
}
|
||||
|
||||
std::string fl_tmp = fl_out;
|
||||
@ -159,62 +159,62 @@ int main(int argc, char* argv[])
|
||||
|
||||
try
|
||||
{
|
||||
QPDF file;
|
||||
file.processFile(fl_in);
|
||||
QPDF file;
|
||||
file.processFile(fl_in);
|
||||
|
||||
QPDFObjectHandle filetrailer = file.getTrailer();
|
||||
QPDFObjectHandle fileinfo;
|
||||
QPDFObjectHandle filetrailer = file.getTrailer();
|
||||
QPDFObjectHandle fileinfo;
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it =
|
||||
Keys.begin(); Keys.end() != it; ++it)
|
||||
{
|
||||
if (! fileinfo.isInitialized())
|
||||
{
|
||||
if (filetrailer.hasKey("/Info"))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info has info");
|
||||
fileinfo = filetrailer.getKey("/Info");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info file no info");
|
||||
fileinfo = QPDFObjectHandle::newDictionary();
|
||||
filetrailer.replaceKey("/Info", fileinfo);
|
||||
}
|
||||
}
|
||||
if (it->second == "")
|
||||
{
|
||||
fileinfo.removeKey(it->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPDFObjectHandle elt = fileinfo.newString(it->second);
|
||||
elt.makeDirect();
|
||||
fileinfo.replaceKey(it->first, elt);
|
||||
}
|
||||
}
|
||||
QPDFWriter w(file, fl_tmp.c_str());
|
||||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.setLinearization(true);
|
||||
w.setStaticID(static_id); // for testing only
|
||||
w.write();
|
||||
for (std::map<std::string, std::string>::const_iterator it =
|
||||
Keys.begin(); Keys.end() != it; ++it)
|
||||
{
|
||||
if (! fileinfo.isInitialized())
|
||||
{
|
||||
if (filetrailer.hasKey("/Info"))
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info has info");
|
||||
fileinfo = filetrailer.getKey("/Info");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("examples", "pdf-mod-info file no info");
|
||||
fileinfo = QPDFObjectHandle::newDictionary();
|
||||
filetrailer.replaceKey("/Info", fileinfo);
|
||||
}
|
||||
}
|
||||
if (it->second == "")
|
||||
{
|
||||
fileinfo.removeKey(it->first);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPDFObjectHandle elt = fileinfo.newString(it->second);
|
||||
elt.makeDirect();
|
||||
fileinfo.replaceKey(it->first, elt);
|
||||
}
|
||||
}
|
||||
QPDFWriter w(file, fl_tmp.c_str());
|
||||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.setLinearization(true);
|
||||
w.setStaticID(static_id); // for testing only
|
||||
w.write();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
(void) remove(fl_out);
|
||||
QUtil::os_wrapper("rename " + fl_tmp + " " + std::string(fl_out),
|
||||
rename(fl_tmp.c_str(), fl_out));
|
||||
(void) remove(fl_out);
|
||||
QUtil::os_wrapper("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);
|
||||
std::cerr << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -11,9 +11,9 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " outfile.pdf"
|
||||
<< std::endl
|
||||
<< "Create some name/number trees and write to a file"
|
||||
<< std::endl;
|
||||
<< std::endl
|
||||
<< "Create some name/number trees and write to a file"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -24,12 +24,12 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
char const* outfilename = argv[1];
|
||||
|
@ -10,7 +10,7 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " filename" << std::endl
|
||||
<< "Prints the number of pages in filename" << std::endl;
|
||||
<< "Prints the number of pages in filename" << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -21,34 +21,34 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
|
||||
{
|
||||
std::cout << whoami << " version 1.3" << std::endl;
|
||||
exit(0);
|
||||
std::cout << whoami << " version 1.3" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
char const* filename = argv[1];
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle pages = root.getKey("/Pages");
|
||||
QPDFObjectHandle count = pages.getKey("/Count");
|
||||
std::cout << count.getIntValue() << std::endl;
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
QPDFObjectHandle root = pdf.getRoot();
|
||||
QPDFObjectHandle pages = root.getKey("/Pages");
|
||||
QPDFObjectHandle count = pages.getKey("/Count");
|
||||
std::cout << count.getIntValue() << std::endl;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -17,10 +17,10 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " infile pagefile outfile"
|
||||
<< std::endl
|
||||
<< "Stamp page 1 of pagefile on every page of infile,"
|
||||
<< std::endl
|
||||
<< "Stamp page 1 of pagefile on every page of infile,"
|
||||
<< " writing to outfile"
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
@ -108,8 +108,8 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ static char const* whoami = 0;
|
||||
void usage()
|
||||
{
|
||||
std::cerr << "Usage: " << whoami << " filename page-number" << std::endl
|
||||
<< "Prints a dump of the objects in the content streams"
|
||||
<< "Prints a dump of the objects in the content streams"
|
||||
<< " of the given page." << std::endl
|
||||
<< "Pages are numbered from 1." << std::endl;
|
||||
exit(2);
|
||||
@ -66,20 +66,20 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
char const* filename = argv[1];
|
||||
int pageno = QUtil::string_to_int(argv[2]);
|
||||
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
QPDF pdf;
|
||||
pdf.processFile(filename);
|
||||
std::vector<QPDFPageObjectHelper> pages =
|
||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||
if ((pageno < 1) || (QIntC::to_size(pageno) > pages.size()))
|
||||
@ -93,8 +93,8 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -13,8 +13,8 @@ static char const* whoami = 0;
|
||||
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
|
||||
<< "Set the value of all text fields to a specified value"
|
||||
<< std::endl;
|
||||
exit(2);
|
||||
}
|
||||
@ -27,7 +27,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 4)
|
||||
@ -47,8 +47,8 @@ int main(int argc, char* argv[])
|
||||
|
||||
try
|
||||
{
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename);
|
||||
QPDF qpdf;
|
||||
qpdf.processFile(infilename);
|
||||
|
||||
// We will iterate through form fields by starting at the page
|
||||
// level and looking at each field for each page. We could
|
||||
@ -94,16 +94,16 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
// Write out a new file
|
||||
QPDFWriter w(qpdf, outfilename);
|
||||
w.setStaticID(true); // for testing only
|
||||
w.write();
|
||||
w.write();
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
std::cerr << whoami << " processing file " << infilename << ": "
|
||||
<< e.what() << std::endl;
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -38,13 +38,13 @@ static void process(char const* whoami,
|
||||
outpdf.emptyPDF();
|
||||
QPDFPageDocumentHelper(outpdf).addPage(page, false);
|
||||
QPDFWriter outpdfw(outpdf, outfile.c_str());
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
outpdfw.setStaticID(true); // for testing only
|
||||
outpdfw.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
if (static_id)
|
||||
{
|
||||
// For the test suite, uncompress streams and use static
|
||||
// IDs.
|
||||
outpdfw.setStaticID(true); // for testing only
|
||||
outpdfw.setStreamDataMode(qpdf_s_uncompress);
|
||||
}
|
||||
outpdfw.write();
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
// For test suite
|
||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
||||
|
@ -30,7 +30,7 @@ int main(int argc, char* argv[])
|
||||
// For libtool's sake....
|
||||
if (strncmp(whoami, "lt-", 3) == 0)
|
||||
{
|
||||
whoami += 3;
|
||||
whoami += 3;
|
||||
}
|
||||
|
||||
if (argc != 1)
|
||||
|
@ -26,20 +26,20 @@ int main(int argc, char* argv[])
|
||||
|
||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
whoami = p + 1;
|
||||
}
|
||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
||||
{
|
||||
whoami = p + 1;
|
||||
whoami = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
whoami = argv[0];
|
||||
whoami = argv[0];
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
usage();
|
||||
usage();
|
||||
}
|
||||
|
||||
infile = argv[1];
|
||||
|
@ -15,38 +15,38 @@ foreach my $show ("", " --show-open")
|
||||
{
|
||||
my $xshow = $show ? $show : "x";
|
||||
my $xstyle = $style ? $style : "x";
|
||||
my $out = "test.$xshow.$xstyle.out";
|
||||
$out =~ s/ //g;
|
||||
$td->runtest("show:$show, style:$style",
|
||||
{$td->COMMAND => "pdf-bookmarks $show $style 1.pdf"},
|
||||
{$td->FILE => $out, $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
my $out = "test.$xshow.$xstyle.out";
|
||||
$out =~ s/ //g;
|
||||
$td->runtest("show:$show, style:$style",
|
||||
{$td->COMMAND => "pdf-bookmarks $show $style 1.pdf"},
|
||||
{$td->FILE => $out, $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
}
|
||||
}
|
||||
$td->runtest("no bookmarks",
|
||||
{$td->COMMAND => "pdf-bookmarks 2.pdf"},
|
||||
{$td->STRING => "2.pdf has no bookmarks\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-bookmarks 2.pdf"},
|
||||
{$td->STRING => "2.pdf has no bookmarks\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("bad",
|
||||
{$td->COMMAND => "pdf-bookmarks 3.pdf"},
|
||||
{$td->REGEXP => "pdf-bookmarks processing file 3.pdf: " .
|
||||
".*unable to find trailer.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-bookmarks 3.pdf"},
|
||||
{$td->REGEXP => "pdf-bookmarks processing file 3.pdf: " .
|
||||
".*unable to find trailer.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("encrypted, targets",
|
||||
{$td->COMMAND => "pdf-bookmarks --show-targets 4.pdf user"},
|
||||
{$td->FILE => "encrypted.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-bookmarks --show-targets 4.pdf user"},
|
||||
{$td->FILE => "encrypted.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("bookmarks deleted",
|
||||
{$td->COMMAND => "pdf-bookmarks 5.pdf user"},
|
||||
{$td->STRING => "5.pdf has no bookmarks\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-bookmarks 5.pdf user"},
|
||||
{$td->STRING => "5.pdf has no bookmarks\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("non-trivial pdf doc to unicode",
|
||||
{$td->COMMAND => "pdf-bookmarks issue-179.pdf"},
|
||||
|
@ -10,8 +10,8 @@ require TestDriver;
|
||||
my $td = new TestDriver('pdf-count-strings');
|
||||
|
||||
$td->runtest("filter tokens",
|
||||
{$td->COMMAND => "pdf-count-strings in.pdf"},
|
||||
{$td->FILE => "out", $td->EXIT_STATUS => 0},
|
||||
{$td->COMMAND => "pdf-count-strings in.pdf"},
|
||||
{$td->FILE => "out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->report(1);
|
||||
|
@ -12,8 +12,8 @@ cleanup();
|
||||
my $td = new TestDriver('create');
|
||||
|
||||
$td->runtest("create a simple PDF",
|
||||
{$td->COMMAND => "pdf-create a.pdf"},
|
||||
{$td->FILE => "create.out", $td->EXIT_STATUS => 0},
|
||||
{$td->COMMAND => "pdf-create a.pdf"},
|
||||
{$td->FILE => "create.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
cleanup();
|
||||
|
@ -12,16 +12,16 @@ my $td = new TestDriver('double-page-size');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("double page size",
|
||||
{$td->COMMAND => ['pdf-double-page-size', ' --static-id',
|
||||
{$td->COMMAND => ['pdf-double-page-size', ' --static-id',
|
||||
'in.pdf', 'a.pdf']},
|
||||
{$td->STRING =>
|
||||
"pdf-double-page-size: new file written to a.pdf\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->STRING =>
|
||||
"pdf-double-page-size: new file written to a.pdf\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -12,12 +12,12 @@ my $td = new TestDriver('pdf-filter-tokens');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("filter tokens",
|
||||
{$td->COMMAND => "pdf-filter-tokens in.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "pdf-filter-tokens in.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -12,16 +12,16 @@ my $td = new TestDriver('invert-images');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("invert images",
|
||||
{$td->COMMAND => ['pdf-invert-images', ' --static-id',
|
||||
{$td->COMMAND => ['pdf-invert-images', ' --static-id',
|
||||
'in.pdf', 'a.pdf']},
|
||||
{$td->STRING =>
|
||||
"pdf-invert-images: new file written to a.pdf\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->STRING =>
|
||||
"pdf-invert-images: new file written to a.pdf\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -14,14 +14,14 @@ my $td = new TestDriver('linearize');
|
||||
my $qpdf = $ENV{'QPDF_BIN'} or die;
|
||||
|
||||
$td->runtest("linearize",
|
||||
{$td->COMMAND => "pdf-linearize input.pdf '' a.pdf"},
|
||||
{$td->REGEXP => '(?s).*input\.pdf progress: \d+\%.*',
|
||||
{$td->COMMAND => "pdf-linearize input.pdf '' a.pdf"},
|
||||
{$td->REGEXP => '(?s).*input\.pdf progress: \d+\%.*',
|
||||
$td->EXIT_STATUS => 0});
|
||||
|
||||
$td->runtest("check",
|
||||
{$td->COMMAND => "$qpdf --check a.pdf"},
|
||||
{$td->FILE => "check.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$qpdf --check a.pdf"},
|
||||
{$td->FILE => "check.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -16,65 +16,65 @@ my $qpdf = $ENV{'QPDF_BIN'} or die;
|
||||
cleanup();
|
||||
|
||||
$td->runtest("usage #1",
|
||||
{$td->COMMAND => "$prg --in target.pdf"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$prg --in target.pdf"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("usage #2",
|
||||
{$td->COMMAND => "$prg --key abc --val def"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$prg --key abc --val def"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("usage #3",
|
||||
{$td->COMMAND => "$prg --key abc --val def abc"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$prg --key abc --val def abc"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("usage #4",
|
||||
{$td->COMMAND => "$prg --in source1.pdf --key date --val 01/01/01 --val 12/12/12"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$prg --in source1.pdf --key date --val 01/01/01 --val 12/12/12"},
|
||||
{$td->FILE => "usage.out",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("dump #1",
|
||||
{$td->COMMAND => "$prg --dump files/source1.pdf"},
|
||||
{$td->FILE => "dump.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$prg --dump files/source1.pdf"},
|
||||
{$td->FILE => "dump.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("dump #2",
|
||||
{$td->COMMAND => "$prg --dump files/no-info.pdf"},
|
||||
{$td->STRING => "",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "$prg --dump files/no-info.pdf"},
|
||||
{$td->STRING => "",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("dump #3",
|
||||
{$td->COMMAND => "$prg --dump files/empty-info.pdf"},
|
||||
{$td->STRING => "",
|
||||
$td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "$prg --dump files/empty-info.pdf"},
|
||||
{$td->STRING => "",
|
||||
$td->EXIT_STATUS => 0});
|
||||
|
||||
run_and_cmp("modify Subject",
|
||||
"$prg --in files/source1.pdf --out out.pdf --key Subject " .
|
||||
"--val \"Export Business\"",
|
||||
"", "out.pdf", "files/1.qdf");
|
||||
"$prg --in files/source1.pdf --out out.pdf --key Subject " .
|
||||
"--val \"Export Business\"",
|
||||
"", "out.pdf", "files/1.qdf");
|
||||
|
||||
run_and_cmp("add Subject, remove Producer, modify CreationDate",
|
||||
"$prg --in files/source2.pdf --out out.pdf --key Subject " .
|
||||
"--val \"Tammlin\" --key Producer --key CreationDate --val 12/12",
|
||||
"", "out.pdf", "files/2.qdf");
|
||||
"$prg --in files/source2.pdf --out out.pdf --key Subject " .
|
||||
"--val \"Tammlin\" --key Producer --key CreationDate --val 12/12",
|
||||
"", "out.pdf", "files/2.qdf");
|
||||
|
||||
run_and_cmp("add Subject (empty-info file)",
|
||||
"$prg --in files/empty-info.pdf --out out.pdf --key Subject " .
|
||||
"--val Tammlin",
|
||||
"", "out.pdf", "files/3.qdf");
|
||||
"$prg --in files/empty-info.pdf --out out.pdf --key Subject " .
|
||||
"--val Tammlin",
|
||||
"", "out.pdf", "files/3.qdf");
|
||||
|
||||
copy("files/no-info.pdf", "no-info.pdf") or die "can't copy no-info: $!";
|
||||
run_and_cmp("in-place Producer added (no-info file)",
|
||||
"$prg --in no-info.pdf --key Producer --val \"Obivan Kinobi\"",
|
||||
"", "no-info.pdf", "files/4.qdf");
|
||||
"$prg --in no-info.pdf --key Producer --val \"Obivan Kinobi\"",
|
||||
"", "no-info.pdf", "files/4.qdf");
|
||||
|
||||
cleanup();
|
||||
|
||||
@ -89,12 +89,12 @@ sub run_and_cmp
|
||||
{
|
||||
my ($dsc, $cmd, $out, $fout, $fexp) = @_;
|
||||
$td->runtest($dsc,
|
||||
{$td->COMMAND => "$cmd --static-id"},
|
||||
{$td->STRING => $out,
|
||||
$td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "$cmd --static-id"},
|
||||
{$td->STRING => $out,
|
||||
$td->EXIT_STATUS => 0});
|
||||
$td->runtest("$dsc output",
|
||||
{$td->COMMAND => "$qpdf --static-id" .
|
||||
" --no-original-object-ids -qdf $fout -"},
|
||||
{$td->FILE => $fexp,
|
||||
$td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "$qpdf --static-id" .
|
||||
" --no-original-object-ids -qdf $fout -"},
|
||||
{$td->FILE => $fexp,
|
||||
$td->EXIT_STATUS => 0});
|
||||
}
|
||||
|
@ -12,13 +12,13 @@ my $td = new TestDriver('name-number-tree');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("name/number tree",
|
||||
{$td->COMMAND => 'pdf-name-number-tree a.pdf'},
|
||||
{$td->FILE => 'nn.out', $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => 'pdf-name-number-tree a.pdf'},
|
||||
{$td->FILE => 'nn.out', $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -10,14 +10,14 @@ require TestDriver;
|
||||
my $td = new TestDriver('pdf-npages');
|
||||
|
||||
$td->runtest("normal",
|
||||
{$td->COMMAND => "pdf-npages minimal.pdf"},
|
||||
{$td->STRING => "1\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-npages minimal.pdf"},
|
||||
{$td->STRING => "1\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->runtest("error",
|
||||
{$td->COMMAND => "pdf-npages bad"},
|
||||
{$td->REGEXP => "pdf-npages: bad: unable to find trailer.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-npages bad"},
|
||||
{$td->REGEXP => "pdf-npages: bad: unable to find trailer.*",
|
||||
$td->EXIT_STATUS => 2},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->report(2);
|
||||
|
@ -12,18 +12,18 @@ my $td = new TestDriver('overlay-page');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("overlay-page",
|
||||
{$td->COMMAND => "pdf-overlay-page in.pdf stamp.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "pdf-overlay-page in.pdf stamp.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("compare files",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
|
||||
$td->runtest("overlay-page with fields/ annotations",
|
||||
{$td->COMMAND => "pdf-overlay-page in.pdf annotations.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "pdf-overlay-page in.pdf annotations.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("compare files",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "annotations-out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "annotations-out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -10,8 +10,8 @@ require TestDriver;
|
||||
my $td = new TestDriver('pdf-parse-content');
|
||||
|
||||
$td->runtest("parse content",
|
||||
{$td->COMMAND => "pdf-parse-content input.pdf 1"},
|
||||
{$td->FILE => "content.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
{$td->COMMAND => "pdf-parse-content input.pdf 1"},
|
||||
{$td->FILE => "content.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$td->report(1);
|
||||
|
@ -12,16 +12,16 @@ my $td = new TestDriver('pdf-split-pages');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("split",
|
||||
{$td->COMMAND => "pdf-split-pages ' --static-id' in.pdf out"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "pdf-split-pages ' --static-id' in.pdf out"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
|
||||
$td->runtest("check page 1",
|
||||
{$td->FILE => "out1.pdf"},
|
||||
{$td->FILE => "exp1.pdf"});
|
||||
{$td->FILE => "out1.pdf"},
|
||||
{$td->FILE => "exp1.pdf"});
|
||||
|
||||
$td->runtest("check page 2",
|
||||
{$td->FILE => "out2.pdf"},
|
||||
{$td->FILE => "exp2.pdf"});
|
||||
{$td->FILE => "out2.pdf"},
|
||||
{$td->FILE => "exp2.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -12,8 +12,8 @@ cleanup();
|
||||
my $td = new TestDriver('qpdf-job');
|
||||
|
||||
$td->runtest("qpdf-job",
|
||||
{$td->COMMAND => "qpdf-job"},
|
||||
{$td->FILE => "out", $td->EXIT_STATUS => 0},
|
||||
{$td->COMMAND => "qpdf-job"},
|
||||
{$td->FILE => "out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
for (my $i = 1; $i <= 3; ++$i)
|
||||
{
|
||||
|
@ -12,12 +12,12 @@ cleanup();
|
||||
my $td = new TestDriver('qpdfjob-c');
|
||||
|
||||
$td->runtest("qpdfjob-c",
|
||||
{$td->COMMAND => "qpdfjob-c in.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
{$td->COMMAND => "qpdfjob-c in.pdf a.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -12,11 +12,11 @@ my $td = new TestDriver('pdf-set-form-values');
|
||||
cleanup();
|
||||
|
||||
$td->runtest("set form values",
|
||||
{$td->COMMAND => "pdf-set-form-values form-in.pdf a.pdf soup"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
{$td->COMMAND => "pdf-set-form-values form-in.pdf a.pdf soup"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("compare files",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "form-out.pdf"});
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "form-out.pdf"});
|
||||
|
||||
cleanup();
|
||||
|
||||
|
@ -107,7 +107,7 @@ FuzzHelper::testWrite()
|
||||
w->setStaticID(true);
|
||||
w->setObjectStreamMode(qpdf_o_disable);
|
||||
w->setR3EncryptionParameters(
|
||||
"u", "o", true, true, true, true, true, true, qpdf_r3p_full);
|
||||
"u", "o", true, true, true, true, true, true, qpdf_r3p_full);
|
||||
doWrite(w);
|
||||
|
||||
q = getQpdf();
|
||||
|
@ -32,11 +32,11 @@
|
||||
enum qpdf_error_code_e
|
||||
{
|
||||
qpdf_e_success = 0,
|
||||
qpdf_e_internal, /* logic/programming error -- indicates bug */
|
||||
qpdf_e_system, /* I/O error, memory error, etc. */
|
||||
qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */
|
||||
qpdf_e_password, /* incorrect password for encrypted file */
|
||||
qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */
|
||||
qpdf_e_internal, /* logic/programming error -- indicates bug */
|
||||
qpdf_e_system, /* I/O error, memory error, etc. */
|
||||
qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */
|
||||
qpdf_e_password, /* incorrect password for encrypted file */
|
||||
qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */
|
||||
qpdf_e_pages, /* erroneous or unsupported pages structure */
|
||||
qpdf_e_object, /* type/bounds errors accessing objects */
|
||||
};
|
||||
@ -77,15 +77,15 @@ enum qpdf_object_type_e {
|
||||
|
||||
enum qpdf_object_stream_e
|
||||
{
|
||||
qpdf_o_disable = 0, /* disable object streams */
|
||||
qpdf_o_preserve, /* preserve object streams */
|
||||
qpdf_o_generate /* generate object streams */
|
||||
qpdf_o_disable = 0, /* disable object streams */
|
||||
qpdf_o_preserve, /* preserve object streams */
|
||||
qpdf_o_generate /* generate object streams */
|
||||
};
|
||||
enum qpdf_stream_data_e
|
||||
{
|
||||
qpdf_s_uncompress = 0, /* uncompress stream data */
|
||||
qpdf_s_preserve, /* preserve stream data compression */
|
||||
qpdf_s_compress /* compress stream data */
|
||||
qpdf_s_uncompress = 0, /* uncompress stream data */
|
||||
qpdf_s_preserve, /* preserve stream data compression */
|
||||
qpdf_s_compress /* compress stream data */
|
||||
};
|
||||
|
||||
/* Stream data flags */
|
||||
@ -109,22 +109,22 @@ enum qpdf_stream_decode_level_e
|
||||
|
||||
enum qpdf_r3_print_e
|
||||
{
|
||||
qpdf_r3p_full = 0, /* allow all printing */
|
||||
qpdf_r3p_low, /* allow only low-resolution printing */
|
||||
qpdf_r3p_none /* allow no printing */
|
||||
qpdf_r3p_full = 0, /* allow all printing */
|
||||
qpdf_r3p_low, /* allow only low-resolution printing */
|
||||
qpdf_r3p_none /* allow no printing */
|
||||
};
|
||||
|
||||
/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It
|
||||
* corresponds to options in Acrobat 5's menus. The new interface in
|
||||
* QPDFWriter offers more granularity and no longer uses this type.
|
||||
*/
|
||||
enum qpdf_r3_modify_e /* Allowed changes: */
|
||||
enum qpdf_r3_modify_e /* Allowed changes: */
|
||||
{
|
||||
qpdf_r3m_all = 0, /* All editing */
|
||||
qpdf_r3m_all = 0, /* All editing */
|
||||
qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */
|
||||
qpdf_r3m_form, /* Fill forms, signing, assembly */
|
||||
qpdf_r3m_assembly, /* Only document assembly */
|
||||
qpdf_r3m_none /* No modifications */
|
||||
qpdf_r3m_form, /* Fill forms, signing, assembly */
|
||||
qpdf_r3m_assembly, /* Only document assembly */
|
||||
qpdf_r3m_none /* No modifications */
|
||||
};
|
||||
|
||||
/* Form field flags from the PDF spec */
|
||||
|
@ -36,7 +36,7 @@ class Pl_Flate: public Pipeline
|
||||
|
||||
QPDF_DLL
|
||||
Pl_Flate(char const* identifier, Pipeline* next,
|
||||
action_e action, unsigned int out_bufsize = def_bufsize);
|
||||
action_e action, unsigned int out_bufsize = def_bufsize);
|
||||
QPDF_DLL
|
||||
virtual ~Pl_Flate();
|
||||
|
||||
|
@ -95,8 +95,8 @@ 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 = 0);
|
||||
char const* buf, size_t length,
|
||||
char const* password = 0);
|
||||
|
||||
// Parse a PDF file loaded from a custom InputSource. If you have
|
||||
// your own method of retrieving a PDF file, you can subclass
|
||||
@ -308,7 +308,7 @@ class QPDF
|
||||
void swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2);
|
||||
QPDF_DLL
|
||||
void swapObjects(int objid1, int generation1,
|
||||
int objid2, int generation2);
|
||||
int objid2, int generation2);
|
||||
|
||||
// Replace a reserved object. This is a wrapper around
|
||||
// replaceObject but it guarantees that the underlying object is a
|
||||
@ -373,37 +373,37 @@ class QPDF
|
||||
{
|
||||
public:
|
||||
|
||||
// This class holds data read from the encryption dictionary.
|
||||
EncryptionData(int V, int R, int Length_bytes, int P,
|
||||
std::string const& O, std::string const& U,
|
||||
// This class holds data read from the encryption dictionary.
|
||||
EncryptionData(int V, int R, int Length_bytes, int P,
|
||||
std::string const& O, std::string const& U,
|
||||
std::string const& OE, std::string const& UE,
|
||||
std::string const& Perms,
|
||||
std::string const& id1, bool encrypt_metadata) :
|
||||
V(V),
|
||||
R(R),
|
||||
Length_bytes(Length_bytes),
|
||||
P(P),
|
||||
O(O),
|
||||
U(U),
|
||||
std::string const& id1, bool encrypt_metadata) :
|
||||
V(V),
|
||||
R(R),
|
||||
Length_bytes(Length_bytes),
|
||||
P(P),
|
||||
O(O),
|
||||
U(U),
|
||||
OE(OE),
|
||||
UE(UE),
|
||||
Perms(Perms),
|
||||
id1(id1),
|
||||
encrypt_metadata(encrypt_metadata)
|
||||
{
|
||||
}
|
||||
id1(id1),
|
||||
encrypt_metadata(encrypt_metadata)
|
||||
{
|
||||
}
|
||||
|
||||
int getV() const;
|
||||
int getR() const;
|
||||
int getLengthBytes() const;
|
||||
int getP() const;
|
||||
std::string const& getO() const;
|
||||
std::string const& getU() const;
|
||||
std::string const& getOE() const;
|
||||
std::string const& getUE() const;
|
||||
std::string const& getPerms() const;
|
||||
std::string const& getId1() const;
|
||||
bool getEncryptMetadata() const;
|
||||
int getV() const;
|
||||
int getR() const;
|
||||
int getLengthBytes() const;
|
||||
int getP() const;
|
||||
std::string const& getO() const;
|
||||
std::string const& getU() const;
|
||||
std::string const& getOE() const;
|
||||
std::string const& getUE() const;
|
||||
std::string const& getPerms() const;
|
||||
std::string const& getId1() const;
|
||||
bool getEncryptMetadata() const;
|
||||
|
||||
void setO(std::string const&);
|
||||
void setU(std::string const&);
|
||||
@ -417,17 +417,17 @@ class QPDF
|
||||
EncryptionData(EncryptionData const&) = delete;
|
||||
EncryptionData& operator=(EncryptionData const&) = delete;
|
||||
|
||||
int V;
|
||||
int R;
|
||||
int Length_bytes;
|
||||
int P;
|
||||
std::string O;
|
||||
std::string U;
|
||||
int V;
|
||||
int R;
|
||||
int Length_bytes;
|
||||
int P;
|
||||
std::string O;
|
||||
std::string U;
|
||||
std::string OE;
|
||||
std::string UE;
|
||||
std::string Perms;
|
||||
std::string id1;
|
||||
bool encrypt_metadata;
|
||||
std::string id1;
|
||||
bool encrypt_metadata;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
@ -475,25 +475,25 @@ class QPDF
|
||||
static void trim_user_password(std::string& user_password);
|
||||
QPDF_DLL
|
||||
static std::string compute_data_key(
|
||||
std::string const& encryption_key, int objid, int generation,
|
||||
bool use_aes, int encryption_V, int encryption_R);
|
||||
std::string const& encryption_key, int objid, int generation,
|
||||
bool use_aes, int encryption_V, int encryption_R);
|
||||
QPDF_DLL
|
||||
static std::string compute_encryption_key(
|
||||
std::string const& password, EncryptionData const& data);
|
||||
std::string const& password, EncryptionData const& data);
|
||||
|
||||
QPDF_DLL
|
||||
static void compute_encryption_O_U(
|
||||
char const* user_password, char const* owner_password,
|
||||
int V, int R, int key_len, int P, bool encrypt_metadata,
|
||||
std::string const& id1,
|
||||
std::string& O, std::string& U);
|
||||
char const* user_password, char const* owner_password,
|
||||
int V, int R, int key_len, int P, bool encrypt_metadata,
|
||||
std::string const& id1,
|
||||
std::string& O, std::string& U);
|
||||
QPDF_DLL
|
||||
static void compute_encryption_parameters_V5(
|
||||
char const* user_password, char const* owner_password,
|
||||
int V, int R, int key_len, int P, bool encrypt_metadata,
|
||||
std::string const& id1,
|
||||
char const* user_password, char const* owner_password,
|
||||
int V, int R, int key_len, int P, bool encrypt_metadata,
|
||||
std::string const& id1,
|
||||
std::string& encryption_key,
|
||||
std::string& O, std::string& U,
|
||||
std::string& O, std::string& U,
|
||||
std::string& OE, std::string& UE, std::string& Perms);
|
||||
// Return the full user password as stored in the PDF file. For
|
||||
// files encrypted with 40-bit or 128-bit keys, the user password
|
||||
@ -583,7 +583,7 @@ class QPDF
|
||||
// objects for stream dictionary keys it will be regenerating.
|
||||
QPDF_DLL
|
||||
void optimize(std::map<int, int> const& object_stream_data,
|
||||
bool allow_changes = true);
|
||||
bool allow_changes = true);
|
||||
// ABI: make function optional and merge overloaded versions
|
||||
QPDF_DLL
|
||||
void optimize(
|
||||
@ -698,13 +698,13 @@ class QPDF
|
||||
// it can resolve indirect references.
|
||||
class Resolver
|
||||
{
|
||||
friend class QPDFObjectHandle;
|
||||
friend class QPDFObjectHandle;
|
||||
private:
|
||||
static PointerHolder<QPDFObject> resolve(
|
||||
QPDF* qpdf, int objid, int generation)
|
||||
{
|
||||
return qpdf->resolve(objid, generation);
|
||||
}
|
||||
static PointerHolder<QPDFObject> resolve(
|
||||
QPDF* qpdf, int objid, int generation)
|
||||
{
|
||||
return qpdf->resolve(objid, generation);
|
||||
}
|
||||
static bool objectChanged(
|
||||
QPDF* qpdf, QPDFObjGen const& og, PointerHolder<QPDFObject>& oph)
|
||||
{
|
||||
@ -717,14 +717,14 @@ class QPDF
|
||||
// copy stream data.
|
||||
class StreamCopier
|
||||
{
|
||||
friend class QPDFObjectHandle;
|
||||
friend class QPDFObjectHandle;
|
||||
private:
|
||||
static void copyStreamData(QPDF* qpdf,
|
||||
static void copyStreamData(QPDF* qpdf,
|
||||
QPDFObjectHandle const& dest,
|
||||
QPDFObjectHandle const& src)
|
||||
{
|
||||
qpdf->copyStreamData(dest, src);
|
||||
}
|
||||
{
|
||||
qpdf->copyStreamData(dest, src);
|
||||
}
|
||||
};
|
||||
friend class Resolver;
|
||||
|
||||
@ -732,7 +732,7 @@ class QPDF
|
||||
// resolution
|
||||
class ParseGuard
|
||||
{
|
||||
friend class QPDFObjectHandle;
|
||||
friend class QPDFObjectHandle;
|
||||
private:
|
||||
ParseGuard(QPDF* qpdf) :
|
||||
qpdf(qpdf)
|
||||
@ -756,19 +756,19 @@ class QPDF
|
||||
// Pipe class is restricted to QPDF_Stream
|
||||
class Pipe
|
||||
{
|
||||
friend class QPDF_Stream;
|
||||
friend class QPDF_Stream;
|
||||
private:
|
||||
static bool pipeStreamData(QPDF* qpdf, int objid, int generation,
|
||||
qpdf_offset_t offset, size_t length,
|
||||
QPDFObjectHandle dict,
|
||||
Pipeline* pipeline,
|
||||
static bool pipeStreamData(QPDF* qpdf, int objid, int generation,
|
||||
qpdf_offset_t offset, size_t length,
|
||||
QPDFObjectHandle dict,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry)
|
||||
{
|
||||
return qpdf->pipeStreamData(
|
||||
objid, generation, offset, length, dict, pipeline,
|
||||
{
|
||||
return qpdf->pipeStreamData(
|
||||
objid, generation, offset, length, dict, pipeline,
|
||||
suppress_warnings, will_retry);
|
||||
}
|
||||
}
|
||||
};
|
||||
friend class Pipe;
|
||||
|
||||
@ -778,23 +778,23 @@ class QPDF
|
||||
class ObjCache
|
||||
{
|
||||
public:
|
||||
ObjCache() :
|
||||
end_before_space(0),
|
||||
end_after_space(0)
|
||||
{
|
||||
}
|
||||
ObjCache(PointerHolder<QPDFObject> object,
|
||||
qpdf_offset_t end_before_space,
|
||||
qpdf_offset_t end_after_space) :
|
||||
object(object),
|
||||
end_before_space(end_before_space),
|
||||
end_after_space(end_after_space)
|
||||
{
|
||||
}
|
||||
ObjCache() :
|
||||
end_before_space(0),
|
||||
end_after_space(0)
|
||||
{
|
||||
}
|
||||
ObjCache(PointerHolder<QPDFObject> object,
|
||||
qpdf_offset_t end_before_space,
|
||||
qpdf_offset_t end_after_space) :
|
||||
object(object),
|
||||
end_before_space(end_before_space),
|
||||
end_after_space(end_after_space)
|
||||
{
|
||||
}
|
||||
|
||||
PointerHolder<QPDFObject> object;
|
||||
qpdf_offset_t end_before_space;
|
||||
qpdf_offset_t end_after_space;
|
||||
PointerHolder<QPDFObject> object;
|
||||
qpdf_offset_t end_before_space;
|
||||
qpdf_offset_t end_after_space;
|
||||
};
|
||||
|
||||
class ObjCopier
|
||||
@ -861,7 +861,7 @@ class QPDF
|
||||
virtual ~CopiedStreamDataProvider()
|
||||
{
|
||||
}
|
||||
virtual bool provideStreamData(
|
||||
virtual bool provideStreamData(
|
||||
int objid, int generation, Pipeline* pipeline,
|
||||
bool suppress_warnings, bool will_retry) override;
|
||||
void registerForeignStream(QPDFObjGen const& local_og,
|
||||
@ -926,23 +926,23 @@ class QPDF
|
||||
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);
|
||||
bool overwrite = false);
|
||||
void setLastObjectDescription(std::string const& description,
|
||||
int objid, int generation);
|
||||
int objid, int generation);
|
||||
QPDFObjectHandle readObject(
|
||||
PointerHolder<InputSource>, std::string const& description,
|
||||
int objid, int generation, bool in_object_stream);
|
||||
PointerHolder<InputSource>, std::string const& description,
|
||||
int objid, int generation, bool in_object_stream);
|
||||
size_t recoverStreamLength(
|
||||
PointerHolder<InputSource> input, int objid, int generation,
|
||||
qpdf_offset_t stream_offset);
|
||||
PointerHolder<InputSource> input, int objid, int generation,
|
||||
qpdf_offset_t stream_offset);
|
||||
QPDFTokenizer::Token readToken(PointerHolder<InputSource>,
|
||||
size_t max_len = 0);
|
||||
|
||||
QPDFObjectHandle readObjectAtOffset(
|
||||
bool attempt_recovery,
|
||||
qpdf_offset_t offset, std::string const& description,
|
||||
int exp_objid, int exp_generation,
|
||||
int& act_objid, int& act_generation);
|
||||
bool attempt_recovery,
|
||||
qpdf_offset_t offset, std::string const& description,
|
||||
int exp_objid, int exp_generation,
|
||||
int& act_objid, int& act_generation);
|
||||
bool objectChanged(QPDFObjGen const& og, PointerHolder<QPDFObject>& oph);
|
||||
PointerHolder<QPDFObject> resolve(int objid, int generation);
|
||||
void resolveObjectsInStream(int obj_stream_number);
|
||||
@ -950,9 +950,9 @@ class QPDF
|
||||
|
||||
// Calls finish() on the pipeline when done but does not delete it
|
||||
bool pipeStreamData(int objid, int generation,
|
||||
qpdf_offset_t offset, size_t length,
|
||||
QPDFObjectHandle dict,
|
||||
Pipeline* pipeline,
|
||||
qpdf_offset_t offset, size_t length,
|
||||
QPDFObjectHandle dict,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
bool pipeForeignStreamData(
|
||||
@ -973,18 +973,18 @@ class QPDF
|
||||
// Get lists of all objects in order according to the part of a
|
||||
// linearized file that they belong to.
|
||||
void getLinearizedParts(
|
||||
std::map<int, int> const& object_stream_data,
|
||||
std::vector<QPDFObjectHandle>& part4,
|
||||
std::vector<QPDFObjectHandle>& part6,
|
||||
std::vector<QPDFObjectHandle>& part7,
|
||||
std::vector<QPDFObjectHandle>& part8,
|
||||
std::vector<QPDFObjectHandle>& part9);
|
||||
std::map<int, int> const& object_stream_data,
|
||||
std::vector<QPDFObjectHandle>& part4,
|
||||
std::vector<QPDFObjectHandle>& part6,
|
||||
std::vector<QPDFObjectHandle>& part7,
|
||||
std::vector<QPDFObjectHandle>& part8,
|
||||
std::vector<QPDFObjectHandle>& part9);
|
||||
|
||||
void generateHintStream(std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber,
|
||||
PointerHolder<Buffer>& hint_stream,
|
||||
int& S, int& O);
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber,
|
||||
PointerHolder<Buffer>& hint_stream,
|
||||
int& S, int& O);
|
||||
|
||||
// Map object to object stream that contains it
|
||||
void getObjectStreamData(std::map<int, int>&);
|
||||
@ -1020,12 +1020,12 @@ class QPDF
|
||||
std::string const& password, EncryptionData const& data,
|
||||
bool& perms_valid);
|
||||
static void decryptStream(
|
||||
PointerHolder<EncryptionParameters> encp,
|
||||
PointerHolder<EncryptionParameters> encp,
|
||||
PointerHolder<InputSource> file,
|
||||
QPDF& qpdf_for_warning, Pipeline*& pipeline,
|
||||
int objid, int generation,
|
||||
QPDFObjectHandle& stream_dict,
|
||||
std::vector<std::shared_ptr<Pipeline>>& heap);
|
||||
QPDFObjectHandle& stream_dict,
|
||||
std::vector<std::shared_ptr<Pipeline>>& heap);
|
||||
|
||||
// Methods to support object copying
|
||||
void reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
|
||||
@ -1051,118 +1051,118 @@ class QPDF
|
||||
// PDF 1.4: Table F.4
|
||||
struct HPageOffsetEntry
|
||||
{
|
||||
HPageOffsetEntry() :
|
||||
delta_nobjects(0),
|
||||
delta_page_length(0),
|
||||
nshared_objects(0),
|
||||
delta_content_offset(0),
|
||||
delta_content_length(0)
|
||||
{
|
||||
}
|
||||
HPageOffsetEntry() :
|
||||
delta_nobjects(0),
|
||||
delta_page_length(0),
|
||||
nshared_objects(0),
|
||||
delta_content_offset(0),
|
||||
delta_content_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
int delta_nobjects; // 1
|
||||
qpdf_offset_t delta_page_length; // 2
|
||||
int nshared_objects; // 3
|
||||
// vectors' sizes = nshared_objects
|
||||
std::vector<int> shared_identifiers; // 4
|
||||
std::vector<int> shared_numerators; // 5
|
||||
qpdf_offset_t delta_content_offset; // 6
|
||||
int delta_nobjects; // 1
|
||||
qpdf_offset_t delta_page_length; // 2
|
||||
int nshared_objects; // 3
|
||||
// vectors' sizes = nshared_objects
|
||||
std::vector<int> shared_identifiers; // 4
|
||||
std::vector<int> shared_numerators; // 5
|
||||
qpdf_offset_t delta_content_offset; // 6
|
||||
qpdf_offset_t delta_content_length; // 7
|
||||
};
|
||||
|
||||
// PDF 1.4: Table F.3
|
||||
struct HPageOffset
|
||||
{
|
||||
HPageOffset() :
|
||||
min_nobjects(0),
|
||||
first_page_offset(0),
|
||||
nbits_delta_nobjects(0),
|
||||
min_page_length(0),
|
||||
nbits_delta_page_length(0),
|
||||
min_content_offset(0),
|
||||
nbits_delta_content_offset(0),
|
||||
min_content_length(0),
|
||||
nbits_delta_content_length(0),
|
||||
nbits_nshared_objects(0),
|
||||
nbits_shared_identifier(0),
|
||||
nbits_shared_numerator(0),
|
||||
shared_denominator(0)
|
||||
{
|
||||
}
|
||||
HPageOffset() :
|
||||
min_nobjects(0),
|
||||
first_page_offset(0),
|
||||
nbits_delta_nobjects(0),
|
||||
min_page_length(0),
|
||||
nbits_delta_page_length(0),
|
||||
min_content_offset(0),
|
||||
nbits_delta_content_offset(0),
|
||||
min_content_length(0),
|
||||
nbits_delta_content_length(0),
|
||||
nbits_nshared_objects(0),
|
||||
nbits_shared_identifier(0),
|
||||
nbits_shared_numerator(0),
|
||||
shared_denominator(0)
|
||||
{
|
||||
}
|
||||
|
||||
int min_nobjects; // 1
|
||||
qpdf_offset_t first_page_offset; // 2
|
||||
int nbits_delta_nobjects; // 3
|
||||
int min_page_length; // 4
|
||||
int nbits_delta_page_length; // 5
|
||||
int min_content_offset; // 6
|
||||
int nbits_delta_content_offset; // 7
|
||||
int min_content_length; // 8
|
||||
int nbits_delta_content_length; // 9
|
||||
int nbits_nshared_objects; // 10
|
||||
int nbits_shared_identifier; // 11
|
||||
int nbits_shared_numerator; // 12
|
||||
int shared_denominator; // 13
|
||||
// vector size is npages
|
||||
std::vector<HPageOffsetEntry> entries;
|
||||
int min_nobjects; // 1
|
||||
qpdf_offset_t first_page_offset; // 2
|
||||
int nbits_delta_nobjects; // 3
|
||||
int min_page_length; // 4
|
||||
int nbits_delta_page_length; // 5
|
||||
int min_content_offset; // 6
|
||||
int nbits_delta_content_offset; // 7
|
||||
int min_content_length; // 8
|
||||
int nbits_delta_content_length; // 9
|
||||
int nbits_nshared_objects; // 10
|
||||
int nbits_shared_identifier; // 11
|
||||
int nbits_shared_numerator; // 12
|
||||
int shared_denominator; // 13
|
||||
// vector size is npages
|
||||
std::vector<HPageOffsetEntry> entries;
|
||||
};
|
||||
|
||||
// PDF 1.4: Table F.6
|
||||
struct HSharedObjectEntry
|
||||
{
|
||||
HSharedObjectEntry() :
|
||||
delta_group_length(0),
|
||||
signature_present(0),
|
||||
nobjects_minus_one(0)
|
||||
{
|
||||
}
|
||||
HSharedObjectEntry() :
|
||||
delta_group_length(0),
|
||||
signature_present(0),
|
||||
nobjects_minus_one(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Item 3 is a 128-bit signature (unsupported by Acrobat)
|
||||
int delta_group_length; // 1
|
||||
int signature_present; // 2 -- always 0
|
||||
int nobjects_minus_one; // 4 -- always 0
|
||||
// Item 3 is a 128-bit signature (unsupported by Acrobat)
|
||||
int delta_group_length; // 1
|
||||
int signature_present; // 2 -- always 0
|
||||
int nobjects_minus_one; // 4 -- always 0
|
||||
};
|
||||
|
||||
// PDF 1.4: Table F.5
|
||||
struct HSharedObject
|
||||
{
|
||||
HSharedObject() :
|
||||
first_shared_obj(0),
|
||||
first_shared_offset(0),
|
||||
nshared_first_page(0),
|
||||
nshared_total(0),
|
||||
nbits_nobjects(0),
|
||||
min_group_length(0),
|
||||
nbits_delta_group_length(0)
|
||||
{
|
||||
}
|
||||
HSharedObject() :
|
||||
first_shared_obj(0),
|
||||
first_shared_offset(0),
|
||||
nshared_first_page(0),
|
||||
nshared_total(0),
|
||||
nbits_nobjects(0),
|
||||
min_group_length(0),
|
||||
nbits_delta_group_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
int first_shared_obj; // 1
|
||||
qpdf_offset_t first_shared_offset; // 2
|
||||
int nshared_first_page; // 3
|
||||
int nshared_total; // 4
|
||||
int nbits_nobjects; // 5
|
||||
int min_group_length; // 6
|
||||
int nbits_delta_group_length; // 7
|
||||
// vector size is nshared_total
|
||||
std::vector<HSharedObjectEntry> entries;
|
||||
int first_shared_obj; // 1
|
||||
qpdf_offset_t first_shared_offset; // 2
|
||||
int nshared_first_page; // 3
|
||||
int nshared_total; // 4
|
||||
int nbits_nobjects; // 5
|
||||
int min_group_length; // 6
|
||||
int nbits_delta_group_length; // 7
|
||||
// vector size is nshared_total
|
||||
std::vector<HSharedObjectEntry> entries;
|
||||
};
|
||||
|
||||
// PDF 1.4: Table F.9
|
||||
struct HGeneric
|
||||
{
|
||||
HGeneric() :
|
||||
first_object(0),
|
||||
first_object_offset(0),
|
||||
nobjects(0),
|
||||
group_length(0)
|
||||
{
|
||||
}
|
||||
HGeneric() :
|
||||
first_object(0),
|
||||
first_object_offset(0),
|
||||
nobjects(0),
|
||||
group_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
int first_object; // 1
|
||||
qpdf_offset_t first_object_offset; // 2
|
||||
int nobjects; // 3
|
||||
int group_length; // 4
|
||||
int first_object; // 1
|
||||
qpdf_offset_t first_object_offset; // 2
|
||||
int nobjects; // 3
|
||||
int group_length; // 4
|
||||
};
|
||||
|
||||
// Other linearization data structures
|
||||
@ -1170,26 +1170,26 @@ class QPDF
|
||||
// Initialized from Linearization Parameter dictionary
|
||||
struct LinParameters
|
||||
{
|
||||
LinParameters() :
|
||||
file_size(0),
|
||||
first_page_object(0),
|
||||
first_page_end(0),
|
||||
npages(0),
|
||||
xref_zero_offset(0),
|
||||
first_page(0),
|
||||
H_offset(0),
|
||||
H_length(0)
|
||||
{
|
||||
}
|
||||
LinParameters() :
|
||||
file_size(0),
|
||||
first_page_object(0),
|
||||
first_page_end(0),
|
||||
npages(0),
|
||||
xref_zero_offset(0),
|
||||
first_page(0),
|
||||
H_offset(0),
|
||||
H_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
qpdf_offset_t file_size; // /L
|
||||
int first_page_object; // /O
|
||||
qpdf_offset_t first_page_end; // /E
|
||||
int npages; // /N
|
||||
qpdf_offset_t xref_zero_offset; // /T
|
||||
int first_page; // /P
|
||||
qpdf_offset_t H_offset; // offset of primary hint stream
|
||||
qpdf_offset_t H_length; // length of primary hint stream
|
||||
qpdf_offset_t file_size; // /L
|
||||
int first_page_object; // /O
|
||||
qpdf_offset_t first_page_end; // /E
|
||||
int npages; // /N
|
||||
qpdf_offset_t xref_zero_offset; // /T
|
||||
int first_page; // /P
|
||||
qpdf_offset_t H_offset; // offset of primary hint stream
|
||||
qpdf_offset_t H_length; // length of primary hint stream
|
||||
};
|
||||
|
||||
// Computed hint table value data structures. These tables
|
||||
@ -1209,49 +1209,49 @@ class QPDF
|
||||
|
||||
struct CHPageOffsetEntry
|
||||
{
|
||||
CHPageOffsetEntry() :
|
||||
nobjects(0),
|
||||
nshared_objects(0)
|
||||
{
|
||||
}
|
||||
CHPageOffsetEntry() :
|
||||
nobjects(0),
|
||||
nshared_objects(0)
|
||||
{
|
||||
}
|
||||
|
||||
int nobjects;
|
||||
int nshared_objects;
|
||||
// vectors' sizes = nshared_objects
|
||||
std::vector<int> shared_identifiers;
|
||||
int nobjects;
|
||||
int nshared_objects;
|
||||
// vectors' sizes = nshared_objects
|
||||
std::vector<int> shared_identifiers;
|
||||
};
|
||||
|
||||
struct CHPageOffset
|
||||
{
|
||||
// vector size is npages
|
||||
std::vector<CHPageOffsetEntry> entries;
|
||||
// vector size is npages
|
||||
std::vector<CHPageOffsetEntry> entries;
|
||||
};
|
||||
|
||||
struct CHSharedObjectEntry
|
||||
{
|
||||
CHSharedObjectEntry(int object) :
|
||||
object(object)
|
||||
{
|
||||
}
|
||||
CHSharedObjectEntry(int object) :
|
||||
object(object)
|
||||
{
|
||||
}
|
||||
|
||||
int object;
|
||||
int object;
|
||||
};
|
||||
|
||||
// PDF 1.4: Table F.5
|
||||
struct CHSharedObject
|
||||
{
|
||||
CHSharedObject() :
|
||||
first_shared_obj(0),
|
||||
nshared_first_page(0),
|
||||
nshared_total(0)
|
||||
{
|
||||
}
|
||||
CHSharedObject() :
|
||||
first_shared_obj(0),
|
||||
nshared_first_page(0),
|
||||
nshared_total(0)
|
||||
{
|
||||
}
|
||||
|
||||
int first_shared_obj;
|
||||
int nshared_first_page;
|
||||
int nshared_total;
|
||||
// vector size is nshared_total
|
||||
std::vector<CHSharedObjectEntry> entries;
|
||||
int first_shared_obj;
|
||||
int nshared_first_page;
|
||||
int nshared_total;
|
||||
// vector size is nshared_total
|
||||
std::vector<CHSharedObjectEntry> entries;
|
||||
};
|
||||
|
||||
// No need for CHGeneric -- HGeneric is fine as is.
|
||||
@ -1263,33 +1263,33 @@ 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();
|
||||
// type is set to ou_bad
|
||||
ObjUser();
|
||||
|
||||
// type must be ou_root
|
||||
ObjUser(user_e type);
|
||||
// type must be ou_root
|
||||
ObjUser(user_e type);
|
||||
|
||||
// type must be one of ou_page or ou_thumb
|
||||
ObjUser(user_e type, int pageno);
|
||||
// type must be one of ou_page or ou_thumb
|
||||
ObjUser(user_e type, int pageno);
|
||||
|
||||
// type must be one of ou_trailer_key or ou_root_key
|
||||
ObjUser(user_e type, std::string const& key);
|
||||
// type must be one of ou_trailer_key or ou_root_key
|
||||
ObjUser(user_e type, std::string const& key);
|
||||
|
||||
bool operator<(ObjUser const&) const;
|
||||
bool operator<(ObjUser const&) const;
|
||||
|
||||
user_e ou_type;
|
||||
int pageno; // if ou_page;
|
||||
std::string key; // if ou_trailer_key or ou_root_key
|
||||
user_e ou_type;
|
||||
int pageno; // if ou_page;
|
||||
std::string key; // if ou_trailer_key or ou_root_key
|
||||
};
|
||||
|
||||
class PatternFinder: public InputSource::Finder
|
||||
@ -1331,17 +1331,17 @@ class QPDF
|
||||
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&, std::map<int, int> const& object_stream_data);
|
||||
int lengthNextN(int first_object, int n,
|
||||
std::list<std::string>& errors);
|
||||
std::list<std::string>& errors);
|
||||
void checkHPageOffset(std::list<std::string>& errors,
|
||||
std::list<std::string>& warnings,
|
||||
std::vector<QPDFObjectHandle> const& pages,
|
||||
std::map<int, int>& idx_to_obj);
|
||||
std::list<std::string>& warnings,
|
||||
std::vector<QPDFObjectHandle> const& pages,
|
||||
std::map<int, int>& idx_to_obj);
|
||||
void checkHSharedObject(std::list<std::string>& warnings,
|
||||
std::list<std::string>& errors,
|
||||
std::vector<QPDFObjectHandle> const& pages,
|
||||
std::map<int, int>& idx_to_obj);
|
||||
std::list<std::string>& errors,
|
||||
std::vector<QPDFObjectHandle> const& pages,
|
||||
std::map<int, int>& idx_to_obj);
|
||||
void checkHOutlines(std::list<std::string>& warnings);
|
||||
void dumpHPageOffset();
|
||||
void dumpHSharedObject();
|
||||
@ -1349,27 +1349,27 @@ class QPDF
|
||||
qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
|
||||
QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);
|
||||
void calculateLinearizationData(
|
||||
std::map<int, int> const& object_stream_data);
|
||||
std::map<int, int> const& object_stream_data);
|
||||
void pushOutlinesToPart(
|
||||
std::vector<QPDFObjectHandle>& part,
|
||||
std::set<QPDFObjGen>& lc_outlines,
|
||||
std::map<int, int> const& object_stream_data);
|
||||
std::vector<QPDFObjectHandle>& part,
|
||||
std::set<QPDFObjGen>& lc_outlines,
|
||||
std::map<int, int> const& object_stream_data);
|
||||
int outputLengthNextN(
|
||||
int in_object, int n,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
int in_object, int n,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
void calculateHPageOffset(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
void calculateHSharedObject(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
void calculateHOutline(
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
std::map<int, QPDFXRefEntry> const& xref,
|
||||
std::map<int, qpdf_offset_t> const& lengths,
|
||||
std::map<int, int> const& obj_renumber);
|
||||
void writeHPageOffset(BitWriter&);
|
||||
void writeHSharedObject(BitWriter&);
|
||||
void writeHGeneric(BitWriter&, HGeneric&);
|
||||
@ -1380,10 +1380,10 @@ class QPDF
|
||||
void pushInheritedAttributesToPage(bool allow_changes,
|
||||
bool warn_skipped_keys);
|
||||
void pushInheritedAttributesToPageInternal(
|
||||
QPDFObjectHandle,
|
||||
std::map<std::string, std::vector<QPDFObjectHandle> >&,
|
||||
std::vector<QPDFObjectHandle>& all_pages,
|
||||
bool allow_changes, bool warn_skipped_keys,
|
||||
QPDFObjectHandle,
|
||||
std::map<std::string, std::vector<QPDFObjectHandle> >&,
|
||||
std::vector<QPDFObjectHandle>& all_pages,
|
||||
bool allow_changes, bool warn_skipped_keys,
|
||||
std::set<QPDFObjGen>& visited);
|
||||
void updateObjectMaps(
|
||||
ObjUser const& ou, QPDFObjectHandle oh,
|
||||
|
@ -34,10 +34,10 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFExc(qpdf_error_code_e error_code,
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
QPDF_DLL
|
||||
virtual ~QPDFExc() noexcept
|
||||
{
|
||||
@ -66,9 +66,9 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
|
||||
|
||||
private:
|
||||
static std::string createWhat(std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
|
||||
// This class does not use the Members pattern to avoid needless
|
||||
// memory allocations during exception handling.
|
||||
|
@ -76,16 +76,16 @@ class QPDF_DLL_CLASS QPDFObject
|
||||
// Accessor to give specific access to non-public methods
|
||||
class ObjAccessor
|
||||
{
|
||||
friend class QPDF;
|
||||
friend class QPDFObjectHandle;
|
||||
friend class QPDF;
|
||||
friend class QPDFObjectHandle;
|
||||
private:
|
||||
static void releaseResolved(QPDFObject* o)
|
||||
{
|
||||
if (o)
|
||||
{
|
||||
o->releaseResolved();
|
||||
}
|
||||
}
|
||||
static void releaseResolved(QPDFObject* o)
|
||||
{
|
||||
if (o)
|
||||
{
|
||||
o->releaseResolved();
|
||||
}
|
||||
}
|
||||
};
|
||||
friend class ObjAccessor;
|
||||
|
||||
|
@ -63,27 +63,27 @@ class QPDFObjectHandle
|
||||
QPDF_DLL
|
||||
StreamDataProvider(bool supports_retry = false);
|
||||
|
||||
QPDF_DLL
|
||||
virtual ~StreamDataProvider()
|
||||
{
|
||||
}
|
||||
// The implementation of this function must write stream data
|
||||
// to the given pipeline. The stream data must conform to
|
||||
// whatever filters are explicitly associated with the stream.
|
||||
// QPDFWriter may, in some cases, add compression, but if it
|
||||
// does, it will update the filters as needed. Every call to
|
||||
// provideStreamData for a given stream must write the same
|
||||
// data. Note that, when writing linearized files, qpdf will
|
||||
// call your provideStreamData twice, and if it generates
|
||||
// different output, you risk generating invalid output or
|
||||
// having qpdf throw an exception. The object ID and
|
||||
// generation passed to this method are those that belong to
|
||||
// the stream on behalf of which the provider is called. They
|
||||
// may be ignored or used by the implementation for indexing
|
||||
// or other purposes. This information is made available just
|
||||
// to make it more convenient to use a single
|
||||
// StreamDataProvider object to provide data for multiple
|
||||
// streams.
|
||||
QPDF_DLL
|
||||
virtual ~StreamDataProvider()
|
||||
{
|
||||
}
|
||||
// The implementation of this function must write stream data
|
||||
// to the given pipeline. The stream data must conform to
|
||||
// whatever filters are explicitly associated with the stream.
|
||||
// QPDFWriter may, in some cases, add compression, but if it
|
||||
// does, it will update the filters as needed. Every call to
|
||||
// provideStreamData for a given stream must write the same
|
||||
// data. Note that, when writing linearized files, qpdf will
|
||||
// call your provideStreamData twice, and if it generates
|
||||
// different output, you risk generating invalid output or
|
||||
// having qpdf throw an exception. The object ID and
|
||||
// generation passed to this method are those that belong to
|
||||
// the stream on behalf of which the provider is called. They
|
||||
// may be ignored or used by the implementation for indexing
|
||||
// or other purposes. This information is made available just
|
||||
// to make it more convenient to use a single
|
||||
// StreamDataProvider object to provide data for multiple
|
||||
// streams.
|
||||
|
||||
// A few things to keep in mind:
|
||||
//
|
||||
@ -117,14 +117,14 @@ class QPDFObjectHandle
|
||||
// version of the method, which should also return a boolean
|
||||
// indicating whether it ran without errors.
|
||||
QPDF_DLL
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline);
|
||||
virtual void provideStreamData(int objid, int generation,
|
||||
Pipeline* pipeline);
|
||||
QPDF_DLL
|
||||
virtual bool provideStreamData(
|
||||
virtual bool provideStreamData(
|
||||
int objid, int generation, Pipeline* pipeline,
|
||||
bool suppress_warnings, bool will_retry);
|
||||
QPDF_DLL
|
||||
bool supportsRetry();
|
||||
bool supportsRetry();
|
||||
|
||||
private:
|
||||
bool supports_retry;
|
||||
@ -563,7 +563,7 @@ class QPDFObjectHandle
|
||||
static QPDFObjectHandle newArray();
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newArray(
|
||||
std::vector<QPDFObjectHandle> const& items);
|
||||
std::vector<QPDFObjectHandle> const& items);
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newArray(Rectangle const&);
|
||||
QPDF_DLL
|
||||
@ -574,7 +574,7 @@ class QPDFObjectHandle
|
||||
static QPDFObjectHandle newDictionary();
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle newDictionary(
|
||||
std::map<std::string, QPDFObjectHandle> const& items);
|
||||
std::map<std::string, QPDFObjectHandle> const& items);
|
||||
|
||||
// Create an array from a rectangle. Equivalent to the rectangle
|
||||
// form of newArray.
|
||||
@ -1159,7 +1159,7 @@ class QPDFObjectHandle
|
||||
// Return value is whether filtering was attempted.
|
||||
QPDF_DLL
|
||||
bool pipeStreamData(Pipeline*, bool filter,
|
||||
bool normalize, bool compress);
|
||||
bool normalize, bool compress);
|
||||
|
||||
// Replace a stream's dictionary. The new dictionary must be
|
||||
// consistent with the stream's data. This is most appropriately
|
||||
@ -1179,8 +1179,8 @@ class QPDFObjectHandle
|
||||
// decryption filters have been applied, is as presented.
|
||||
QPDF_DLL
|
||||
void replaceStreamData(PointerHolder<Buffer> data,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
|
||||
// Replace the stream's stream data with the given string.
|
||||
// This method will create a copy of the data rather than using
|
||||
@ -1188,8 +1188,8 @@ class QPDFObjectHandle
|
||||
// of replaceStreamData.
|
||||
QPDF_DLL
|
||||
void replaceStreamData(std::string const& data,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
|
||||
// As above, replace this stream's stream data. Instead of
|
||||
// directly providing a buffer with the stream data, call the
|
||||
@ -1218,8 +1218,8 @@ class QPDFObjectHandle
|
||||
// compute the length in advance.
|
||||
QPDF_DLL
|
||||
void replaceStreamData(PointerHolder<StreamDataProvider> provider,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
|
||||
// Starting in qpdf 10.2, you can use C++-11 function objects
|
||||
// instead of StreamDataProvider.
|
||||
@ -1229,8 +1229,8 @@ class QPDFObjectHandle
|
||||
// pass QUtil::file_provider(filename) as provider.
|
||||
QPDF_DLL
|
||||
void replaceStreamData(std::function<void(Pipeline*)> provider,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms);
|
||||
// The provider should write the stream data to the pipeline,
|
||||
// returning true if it succeeded without errors.
|
||||
QPDF_DLL
|
||||
@ -1317,21 +1317,21 @@ class QPDFObjectHandle
|
||||
// making it a friend of the whole QPDFObjectHandle class.
|
||||
class Factory
|
||||
{
|
||||
friend class QPDF;
|
||||
friend class QPDF;
|
||||
private:
|
||||
static QPDFObjectHandle newIndirect(QPDF* qpdf,
|
||||
int objid, int generation)
|
||||
{
|
||||
return QPDFObjectHandle::newIndirect(qpdf, objid, generation);
|
||||
}
|
||||
// object must be dictionary object
|
||||
static QPDFObjectHandle newStream(
|
||||
QPDF* qpdf, int objid, int generation,
|
||||
QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length)
|
||||
{
|
||||
return QPDFObjectHandle::newStream(
|
||||
qpdf, objid, generation, stream_dict, offset, length);
|
||||
}
|
||||
static QPDFObjectHandle newIndirect(QPDF* qpdf,
|
||||
int objid, int generation)
|
||||
{
|
||||
return QPDFObjectHandle::newIndirect(qpdf, objid, generation);
|
||||
}
|
||||
// object must be dictionary object
|
||||
static QPDFObjectHandle newStream(
|
||||
QPDF* qpdf, int objid, int generation,
|
||||
QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length)
|
||||
{
|
||||
return QPDFObjectHandle::newStream(
|
||||
qpdf, objid, generation, stream_dict, offset, length);
|
||||
}
|
||||
};
|
||||
friend class Factory;
|
||||
|
||||
@ -1339,13 +1339,13 @@ class QPDFObjectHandle
|
||||
// call this.
|
||||
class ObjAccessor
|
||||
{
|
||||
friend class QPDF;
|
||||
friend class QPDF;
|
||||
private:
|
||||
static PointerHolder<QPDFObject> getObject(QPDFObjectHandle& o)
|
||||
{
|
||||
o.dereference();
|
||||
return o.obj;
|
||||
}
|
||||
static PointerHolder<QPDFObject> getObject(QPDFObjectHandle& o)
|
||||
{
|
||||
o.dereference();
|
||||
return o.obj;
|
||||
}
|
||||
};
|
||||
friend class ObjAccessor;
|
||||
|
||||
@ -1353,14 +1353,14 @@ class QPDFObjectHandle
|
||||
// releaseResolved().
|
||||
class ReleaseResolver
|
||||
{
|
||||
friend class QPDF_Dictionary;
|
||||
friend class QPDF_Dictionary;
|
||||
friend class QPDF_Stream;
|
||||
friend class SparseOHArray;
|
||||
private:
|
||||
static void releaseResolved(QPDFObjectHandle& o)
|
||||
{
|
||||
o.releaseResolved();
|
||||
}
|
||||
static void releaseResolved(QPDFObjectHandle& o)
|
||||
{
|
||||
o.releaseResolved();
|
||||
}
|
||||
};
|
||||
friend class ReleaseResolver;
|
||||
|
||||
@ -1440,8 +1440,8 @@ class QPDFObjectHandle
|
||||
// Private object factory methods
|
||||
static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation);
|
||||
static QPDFObjectHandle newStream(
|
||||
QPDF* qpdf, int objid, int generation,
|
||||
QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
|
||||
QPDF* qpdf, int objid, int generation,
|
||||
QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
|
||||
|
||||
void typeWarning(char const* expected_type,
|
||||
std::string const& warning);
|
||||
@ -1481,7 +1481,7 @@ class QPDFObjectHandle
|
||||
// a substantial performance penalty since QPDFObjectHandle
|
||||
// objects are copied around so frequently.
|
||||
QPDF* qpdf;
|
||||
int objid; // 0 for direct object
|
||||
int objid; // 0 for direct object
|
||||
int generation;
|
||||
PointerHolder<QPDFObject> obj;
|
||||
bool reserved;
|
||||
|
@ -49,7 +49,7 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
|
||||
|
||||
private:
|
||||
static std::string createWhat(std::string const& description,
|
||||
int system_errno);
|
||||
int system_errno);
|
||||
|
||||
// This class does not use the Members pattern to avoid needless
|
||||
// memory allocations during exception handling.
|
||||
|
@ -40,20 +40,20 @@ class QPDFTokenizer
|
||||
// version 8.
|
||||
enum token_type_e
|
||||
{
|
||||
tt_bad,
|
||||
tt_array_close,
|
||||
tt_array_open,
|
||||
tt_brace_close,
|
||||
tt_brace_open,
|
||||
tt_dict_close,
|
||||
tt_dict_open,
|
||||
tt_integer,
|
||||
tt_name,
|
||||
tt_real,
|
||||
tt_string,
|
||||
tt_null,
|
||||
tt_bool,
|
||||
tt_word,
|
||||
tt_bad,
|
||||
tt_array_close,
|
||||
tt_array_open,
|
||||
tt_brace_close,
|
||||
tt_brace_open,
|
||||
tt_dict_close,
|
||||
tt_dict_open,
|
||||
tt_integer,
|
||||
tt_name,
|
||||
tt_real,
|
||||
tt_string,
|
||||
tt_null,
|
||||
tt_bool,
|
||||
tt_word,
|
||||
tt_eof,
|
||||
tt_space,
|
||||
tt_comment,
|
||||
@ -63,46 +63,46 @@ class QPDFTokenizer
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
Token() : type(tt_bad) {}
|
||||
Token() : type(tt_bad) {}
|
||||
QPDF_DLL
|
||||
Token(token_type_e type, std::string const& value);
|
||||
Token(token_type_e type, std::string const& value,
|
||||
std::string raw_value, std::string error_message) :
|
||||
type(type),
|
||||
value(value),
|
||||
raw_value(raw_value),
|
||||
error_message(error_message)
|
||||
{
|
||||
}
|
||||
token_type_e getType() const
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
std::string const& getValue() const
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
std::string const& getRawValue() const
|
||||
{
|
||||
return this->raw_value;
|
||||
}
|
||||
std::string const& getErrorMessage() const
|
||||
{
|
||||
return this->error_message;
|
||||
}
|
||||
bool operator==(Token const& rhs) const
|
||||
{
|
||||
// Ignore fields other than type and value
|
||||
return ((this->type != tt_bad) &&
|
||||
(this->type == rhs.type) &&
|
||||
(this->value == rhs.value));
|
||||
}
|
||||
Token(token_type_e type, std::string const& value);
|
||||
Token(token_type_e type, std::string const& value,
|
||||
std::string raw_value, std::string error_message) :
|
||||
type(type),
|
||||
value(value),
|
||||
raw_value(raw_value),
|
||||
error_message(error_message)
|
||||
{
|
||||
}
|
||||
token_type_e getType() const
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
std::string const& getValue() const
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
std::string const& getRawValue() const
|
||||
{
|
||||
return this->raw_value;
|
||||
}
|
||||
std::string const& getErrorMessage() const
|
||||
{
|
||||
return this->error_message;
|
||||
}
|
||||
bool operator==(Token const& rhs) const
|
||||
{
|
||||
// Ignore fields other than type and value
|
||||
return ((this->type != tt_bad) &&
|
||||
(this->type == rhs.type) &&
|
||||
(this->value == rhs.value));
|
||||
}
|
||||
|
||||
private:
|
||||
token_type_e type;
|
||||
std::string value;
|
||||
std::string raw_value;
|
||||
std::string error_message;
|
||||
token_type_e type;
|
||||
std::string value;
|
||||
std::string raw_value;
|
||||
std::string error_message;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
|
@ -370,73 +370,73 @@ class QPDFWriter
|
||||
// it unless you have to.
|
||||
QPDF_DLL
|
||||
void setR2EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_print, bool allow_modify,
|
||||
bool allow_extract, bool allow_annotate);
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_print, bool allow_modify,
|
||||
bool allow_extract, bool allow_annotate);
|
||||
// R3 uses RC4, which is a weak cryptographic algorithm. Don't use
|
||||
// it unless you have to.
|
||||
QPDF_DLL
|
||||
void setR3EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
bool allow_assemble, bool allow_annotate_and_form,
|
||||
bool allow_form_filling, bool allow_modify_other,
|
||||
qpdf_r3_print_e print);
|
||||
qpdf_r3_print_e print);
|
||||
// R4 uses RC4, which is a weak cryptographic algorithm, when
|
||||
// use_aes=false. Don't use it unless you have to.
|
||||
QPDF_DLL
|
||||
void setR4EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
bool allow_assemble, bool allow_annotate_and_form,
|
||||
bool allow_form_filling, bool allow_modify_other,
|
||||
qpdf_r3_print_e print, bool encrypt_metadata, bool use_aes);
|
||||
qpdf_r3_print_e print, bool encrypt_metadata, bool use_aes);
|
||||
// R5 is deprecated. Do not use it for production use. Writing
|
||||
// R5 is supported by qpdf primarily to generate test files for
|
||||
// applications that may need to test R5 support.
|
||||
QPDF_DLL
|
||||
void setR5EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
bool allow_assemble, bool allow_annotate_and_form,
|
||||
bool allow_form_filling, bool allow_modify_other,
|
||||
qpdf_r3_print_e print, bool encrypt_metadata);
|
||||
qpdf_r3_print_e print, bool encrypt_metadata);
|
||||
QPDF_DLL
|
||||
void setR6EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
bool allow_assemble, bool allow_annotate_and_form,
|
||||
bool allow_form_filling, bool allow_modify_other,
|
||||
qpdf_r3_print_e print, bool encrypt_metadata_aes);
|
||||
qpdf_r3_print_e print, bool encrypt_metadata_aes);
|
||||
|
||||
// Pre qpdf 8.4.0 API
|
||||
[[deprecated("see newer API above")]]
|
||||
QPDF_DLL
|
||||
void setR3EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify);
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify);
|
||||
[[deprecated("see newer API above")]]
|
||||
QPDF_DLL
|
||||
void setR4EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
||||
bool encrypt_metadata, bool use_aes);
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
||||
bool encrypt_metadata, bool use_aes);
|
||||
[[deprecated("see newer API above")]]
|
||||
QPDF_DLL
|
||||
void setR5EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
||||
bool encrypt_metadata);
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
||||
bool encrypt_metadata);
|
||||
[[deprecated("see newer API above")]]
|
||||
QPDF_DLL
|
||||
void setR6EncryptionParameters(
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
||||
bool encrypt_metadata_aes);
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
||||
bool encrypt_metadata_aes);
|
||||
|
||||
// Create linearized output. Disables qdf mode, content
|
||||
// normalization, and stream prefiltering.
|
||||
@ -494,8 +494,8 @@ class QPDFWriter
|
||||
|
||||
private:
|
||||
// flags used by unparseObject
|
||||
static int const f_stream = 1 << 0;
|
||||
static int const f_filtered = 1 << 1;
|
||||
static int const f_stream = 1 << 0;
|
||||
static int const f_filtered = 1 << 1;
|
||||
static int const f_in_ostream = 1 << 2;
|
||||
static int const f_hex_string = 1 << 3;
|
||||
static int const f_no_encryption = 1 << 4;
|
||||
@ -544,14 +544,14 @@ class QPDFWriter
|
||||
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,
|
||||
bool xref_stream, qpdf_offset_t prev,
|
||||
int linearization_pass);
|
||||
bool willFilterStream(QPDFObjectHandle stream,
|
||||
bool& compress_stream, bool& is_metadata,
|
||||
PointerHolder<Buffer>* stream_data);
|
||||
void unparseObject(QPDFObjectHandle object, int level, int flags,
|
||||
// for stream dictionaries
|
||||
size_t stream_length = 0, bool compress = false);
|
||||
// for stream dictionaries
|
||||
size_t stream_length = 0, bool compress = false);
|
||||
void unparseChild(QPDFObjectHandle child, int level, int flags);
|
||||
void initializeSpecialStreams();
|
||||
void preserveObjectStreams();
|
||||
@ -559,24 +559,24 @@ class QPDFWriter
|
||||
std::string getOriginalID1();
|
||||
void generateID();
|
||||
void interpretR3EncryptionParameters(
|
||||
std::set<int>& bits_to_clear,
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
std::set<int>& bits_to_clear,
|
||||
char const* user_password, char const* owner_password,
|
||||
bool allow_accessibility, bool allow_extract,
|
||||
bool allow_assemble, bool allow_annotate_and_form,
|
||||
bool allow_form_filling, bool allow_modify_other,
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify);
|
||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify);
|
||||
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(
|
||||
char const* user_password, char const* owner_password,
|
||||
int V, int R, int key_len, std::set<int>& bits_to_clear);
|
||||
char const* user_password, char const* owner_password,
|
||||
int V, int R, int key_len, std::set<int>& bits_to_clear);
|
||||
void setEncryptionParametersInternal(
|
||||
int V, int R, int key_len, int P,
|
||||
std::string const& O, std::string const& U,
|
||||
std::string const& OE, std::string const& UE, std::string const& Perms,
|
||||
std::string const& id1, std::string const& user_password,
|
||||
int V, int R, int key_len, int P,
|
||||
std::string const& O, std::string const& U,
|
||||
std::string const& OE, std::string const& UE, std::string const& Perms,
|
||||
std::string const& id1, std::string const& user_password,
|
||||
std::string const& encryption_key);
|
||||
void setDataKey(int objid);
|
||||
int openObject(int objid = 0);
|
||||
@ -679,8 +679,8 @@ class QPDFWriter
|
||||
int encryption_V;
|
||||
int encryption_R;
|
||||
|
||||
std::string id1; // for /ID key of
|
||||
std::string id2; // trailer dictionary
|
||||
std::string id1; // for /ID key of
|
||||
std::string id2; // trailer dictionary
|
||||
std::string final_pdf_version;
|
||||
int final_extension_level;
|
||||
std::string min_pdf_version;
|
||||
|
@ -46,7 +46,7 @@ class QPDFXRefEntry
|
||||
QPDF_DLL
|
||||
int getObjStreamNumber() const; // only for type 2
|
||||
QPDF_DLL
|
||||
int getObjStreamIndex() const; // only for type 2
|
||||
int getObjStreamIndex() const; // only for type 2
|
||||
|
||||
private:
|
||||
// This class does not use the Members pattern to avoid a memory
|
||||
|
@ -274,7 +274,7 @@ extern "C" {
|
||||
*/
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
|
||||
char const* password);
|
||||
char const* password);
|
||||
|
||||
/* Calling qpdf_read_memory causes processMemoryFile to be called
|
||||
* in the C++ API. Otherwise, it behaves in the same way as
|
||||
@ -284,10 +284,10 @@ extern "C" {
|
||||
*/
|
||||
QPDF_DLL
|
||||
QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf,
|
||||
char const* description,
|
||||
char const* buffer,
|
||||
unsigned long long size,
|
||||
char const* password);
|
||||
char const* description,
|
||||
char const* buffer,
|
||||
unsigned long long size,
|
||||
char const* password);
|
||||
|
||||
/* Calling qpdf_empty_pdf initializes this qpdf object with an
|
||||
* empty PDF, making it possible to create a PDF from scratch
|
||||
@ -410,11 +410,11 @@ extern "C" {
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_object_stream_mode(qpdf_data qpdf,
|
||||
enum qpdf_object_stream_e mode);
|
||||
enum qpdf_object_stream_e mode);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_stream_data_mode(qpdf_data qpdf,
|
||||
enum qpdf_stream_data_e mode);
|
||||
enum qpdf_stream_data_e mode);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value);
|
||||
@ -454,77 +454,77 @@ extern "C" {
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_suppress_original_object_IDs(
|
||||
qpdf_data qpdf, QPDF_BOOL value);
|
||||
qpdf_data qpdf, QPDF_BOOL value);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r2_encryption_parameters(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_print, QPDF_BOOL allow_modify,
|
||||
QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate);
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_print, QPDF_BOOL allow_modify,
|
||||
QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r3_encryption_parameters2(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
||||
enum qpdf_r3_print_e print);
|
||||
enum qpdf_r3_print_e print);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r4_encryption_parameters2(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
||||
enum qpdf_r3_print_e print,
|
||||
enum qpdf_r3_print_e print,
|
||||
QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r5_encryption_parameters2(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
||||
enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
|
||||
enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r6_encryption_parameters2(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
||||
enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
|
||||
enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
|
||||
|
||||
/* Pre 8.4.0 encryption API */
|
||||
QPDF_DLL
|
||||
void qpdf_set_r3_encryption_parameters(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify);
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r4_encryption_parameters(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
||||
QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
||||
QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r5_encryption_parameters(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
||||
QPDF_BOOL encrypt_metadata);
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
||||
QPDF_BOOL encrypt_metadata);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_r6_encryption_parameters(
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
||||
QPDF_BOOL encrypt_metadata);
|
||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
||||
QPDF_BOOL encrypt_metadata);
|
||||
|
||||
QPDF_DLL
|
||||
void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value);
|
||||
|
@ -26,12 +26,12 @@ AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key,
|
||||
std::memset(this->rk.get(), 0, rk_bytes);
|
||||
if (encrypt)
|
||||
{
|
||||
this->nrounds = rijndaelSetupEncrypt(
|
||||
this->nrounds = rijndaelSetupEncrypt(
|
||||
this->rk.get(), this->key.get(), keybits);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->nrounds = rijndaelSetupDecrypt(
|
||||
this->nrounds = rijndaelSetupDecrypt(
|
||||
this->rk.get(), this->key.get(), keybits);
|
||||
}
|
||||
}
|
||||
@ -45,33 +45,33 @@ AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
|
||||
{
|
||||
if (this->encrypt)
|
||||
{
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
|
||||
{
|
||||
in_data[i] ^= this->cbc_block[i];
|
||||
}
|
||||
}
|
||||
rijndaelEncrypt(this->rk.get(),
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
|
||||
{
|
||||
in_data[i] ^= this->cbc_block[i];
|
||||
}
|
||||
}
|
||||
rijndaelEncrypt(this->rk.get(),
|
||||
this->nrounds, in_data, out_data);
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
memcpy(this->cbc_block, out_data,
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
memcpy(this->cbc_block, out_data,
|
||||
QPDFCryptoImpl::rijndael_buf_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rijndaelDecrypt(this->rk.get(),
|
||||
rijndaelDecrypt(this->rk.get(),
|
||||
this->nrounds, in_data, out_data);
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
|
||||
{
|
||||
out_data[i] ^= this->cbc_block[i];
|
||||
}
|
||||
memcpy(this->cbc_block, in_data,
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
|
||||
{
|
||||
out_data[i] ^= this->cbc_block[i];
|
||||
}
|
||||
memcpy(this->cbc_block, in_data,
|
||||
QPDFCryptoImpl::rijndael_buf_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ BitStream::reset()
|
||||
bit_offset = 7;
|
||||
if (QIntC::to_uint(nbytes) > static_cast<unsigned int>(-1) / 8)
|
||||
{
|
||||
throw std::runtime_error("array too large for bitstream");
|
||||
throw std::runtime_error("array too large for bitstream");
|
||||
}
|
||||
bits_available = 8 * nbytes;
|
||||
}
|
||||
@ -29,7 +29,7 @@ unsigned long long
|
||||
BitStream::getBits(size_t nbits)
|
||||
{
|
||||
return read_bits(this->p, this->bit_offset,
|
||||
this->bits_available, nbits);
|
||||
this->bits_available, nbits);
|
||||
}
|
||||
|
||||
long long
|
||||
@ -63,14 +63,14 @@ 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");
|
||||
}
|
||||
bit_offset = 7;
|
||||
++p;
|
||||
bits_available -= bits_to_skip;
|
||||
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");
|
||||
}
|
||||
bit_offset = 7;
|
||||
++p;
|
||||
bits_available -= bits_to_skip;
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ BitWriter::flush()
|
||||
{
|
||||
if (bit_offset < 7)
|
||||
{
|
||||
size_t bits_to_write = bit_offset + 1;
|
||||
write_bits(this->ch, this->bit_offset, 0, bits_to_write, this->pl);
|
||||
size_t bits_to_write = bit_offset + 1;
|
||||
write_bits(this->ch, this->bit_offset, 0, bits_to_write, this->pl);
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) :
|
||||
{
|
||||
if (own_memory)
|
||||
{
|
||||
this->buf = (size ? new unsigned char[size] : 0);
|
||||
this->buf = (size ? new unsigned char[size] : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->buf = buf;
|
||||
this->buf = buf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ Buffer::Members::~Members()
|
||||
{
|
||||
if (this->own_memory)
|
||||
{
|
||||
delete [] this->buf;
|
||||
delete [] this->buf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,10 +58,10 @@ Buffer::copy(Buffer const& rhs)
|
||||
if (this != &rhs)
|
||||
{
|
||||
this->m = PointerHolder<Members>(new Members(rhs.m->size, 0, true));
|
||||
if (this->m->size)
|
||||
{
|
||||
memcpy(this->m->buf, rhs.m->buf, this->m->size);
|
||||
}
|
||||
if (this->m->size)
|
||||
{
|
||||
memcpy(this->m->buf, rhs.m->buf, this->m->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ BufferInputSource::~BufferInputSource()
|
||||
{
|
||||
if (this->m->own_memory)
|
||||
{
|
||||
delete this->m->buf;
|
||||
delete this->m->buf;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,9 +56,9 @@ BufferInputSource::findAndSkipNextEOL()
|
||||
qpdf_offset_t end_pos = this->m->max_offset;
|
||||
if (this->m->cur_offset >= end_pos)
|
||||
{
|
||||
this->last_offset = end_pos;
|
||||
this->last_offset = end_pos;
|
||||
this->m->cur_offset = end_pos;
|
||||
return end_pos;
|
||||
return end_pos;
|
||||
}
|
||||
|
||||
qpdf_offset_t result = 0;
|
||||
@ -108,23 +108,23 @@ BufferInputSource::seek(qpdf_offset_t offset, int whence)
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
this->m->cur_offset = offset;
|
||||
break;
|
||||
this->m->cur_offset = offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
QIntC::range_check(this->m->max_offset, offset);
|
||||
this->m->cur_offset = this->m->max_offset + offset;
|
||||
break;
|
||||
this->m->cur_offset = this->m->max_offset + offset;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
QIntC::range_check(this->m->cur_offset, offset);
|
||||
this->m->cur_offset += offset;
|
||||
break;
|
||||
this->m->cur_offset += offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: invalid argument to BufferInputSource::seek");
|
||||
break;
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: invalid argument to BufferInputSource::seek");
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->m->cur_offset < 0)
|
||||
@ -150,8 +150,8 @@ BufferInputSource::read(char* buffer, size_t length)
|
||||
qpdf_offset_t end_pos = this->m->max_offset;
|
||||
if (this->m->cur_offset >= end_pos)
|
||||
{
|
||||
this->last_offset = end_pos;
|
||||
return 0;
|
||||
this->last_offset = end_pos;
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->last_offset = this->m->cur_offset;
|
||||
@ -167,6 +167,6 @@ BufferInputSource::unreadCh(char ch)
|
||||
{
|
||||
if (this->m->cur_offset > 0)
|
||||
{
|
||||
--this->m->cur_offset;
|
||||
--this->m->cur_offset;
|
||||
}
|
||||
}
|
||||
|
@ -61,16 +61,16 @@ ContentNormalizer::handleToken(QPDFTokenizer::Token const& token)
|
||||
// quoting of unprintable characters, etc.
|
||||
writeToken(QPDFTokenizer::Token(
|
||||
QPDFTokenizer::tt_string, token.getValue()));
|
||||
break;
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_name:
|
||||
writeToken(QPDFTokenizer::Token(
|
||||
QPDFTokenizer::tt_name, token.getValue()));
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
writeToken(token);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
value = token.getRawValue();
|
||||
|
@ -15,7 +15,7 @@ FileInputSource::Members::~Members()
|
||||
{
|
||||
if (this->file && this->close_file)
|
||||
{
|
||||
fclose(this->file);
|
||||
fclose(this->file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,9 +108,9 @@ FileInputSource::seek(qpdf_offset_t offset, int whence)
|
||||
{
|
||||
QUtil::os_wrapper(std::string("seek to ") +
|
||||
this->m->filename + ", offset " +
|
||||
QUtil::int_to_string(offset) + " (" +
|
||||
QUtil::int_to_string(whence) + ")",
|
||||
QUtil::seek(this->m->file, offset, whence));
|
||||
QUtil::int_to_string(offset) + " (" +
|
||||
QUtil::int_to_string(whence) + ")",
|
||||
QUtil::seek(this->m->file, offset, whence));
|
||||
}
|
||||
|
||||
void
|
||||
@ -147,5 +147,5 @@ void
|
||||
FileInputSource::unreadCh(char ch)
|
||||
{
|
||||
QUtil::os_wrapper(this->m->filename + ": unread character",
|
||||
ungetc(static_cast<unsigned char>(ch), this->m->file));
|
||||
ungetc(static_cast<unsigned char>(ch), this->m->file));
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ InsecureRandomDataProvider::random()
|
||||
{
|
||||
if (! this->seeded_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.
|
||||
// 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.
|
||||
unsigned int seed = static_cast<unsigned int>(
|
||||
QUtil::get_current_time() ^ 0xcccc);
|
||||
#ifdef HAVE_RANDOM
|
||||
@ -37,7 +37,7 @@ InsecureRandomDataProvider::random()
|
||||
#else
|
||||
srand(seed);
|
||||
#endif
|
||||
this->seeded_random = true;
|
||||
this->seeded_random = true;
|
||||
}
|
||||
|
||||
# ifdef HAVE_RANDOM
|
||||
|
@ -66,28 +66,28 @@ void MD5::encodeFile(char const *filename, qpdf_offset_t up_to_offset)
|
||||
}
|
||||
do
|
||||
{
|
||||
if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size))
|
||||
{
|
||||
to_try = up_to_size - so_far;
|
||||
}
|
||||
len = fread(buffer, 1, to_try, file);
|
||||
if (len > 0)
|
||||
{
|
||||
encodeDataIncrementally(buffer, len);
|
||||
so_far += len;
|
||||
if ((up_to_offset >= 0) && (so_far >= up_to_size))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size))
|
||||
{
|
||||
to_try = up_to_size - so_far;
|
||||
}
|
||||
len = fread(buffer, 1, to_try, file);
|
||||
if (len > 0)
|
||||
{
|
||||
encodeDataIncrementally(buffer, len);
|
||||
so_far += len;
|
||||
if ((up_to_offset >= 0) && (so_far >= up_to_size))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (len > 0);
|
||||
if (ferror(file))
|
||||
{
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
(void) fclose(file);
|
||||
|
||||
@ -108,7 +108,7 @@ void MD5::print()
|
||||
unsigned int i;
|
||||
for (i = 0; i < 16; ++i)
|
||||
{
|
||||
printf("%02x", digest_val[i]);
|
||||
printf("%02x", digest_val[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@ -140,7 +140,7 @@ MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
|
||||
|
||||
bool
|
||||
MD5::checkDataChecksum(char const* const checksum,
|
||||
char const* buf, size_t len)
|
||||
char const* buf, size_t len)
|
||||
{
|
||||
std::string actual_checksum = getDataChecksum(buf, len);
|
||||
return (checksum == actual_checksum);
|
||||
@ -148,17 +148,17 @@ MD5::checkDataChecksum(char const* const checksum,
|
||||
|
||||
bool
|
||||
MD5::checkFileChecksum(char const* const checksum,
|
||||
char const* filename, qpdf_offset_t up_to_offset)
|
||||
char const* filename, qpdf_offset_t up_to_offset)
|
||||
{
|
||||
bool result = false;
|
||||
try
|
||||
{
|
||||
std::string actual_checksum = getFileChecksum(filename, up_to_offset);
|
||||
result = (checksum == actual_checksum);
|
||||
std::string actual_checksum = getFileChecksum(filename, up_to_offset);
|
||||
result = (checksum == actual_checksum);
|
||||
}
|
||||
catch (std::runtime_error const&)
|
||||
{
|
||||
// Ignore -- return false
|
||||
// Ignore -- return false
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ void MD5_native::init()
|
||||
// context.
|
||||
|
||||
void MD5_native::update(unsigned char *input,
|
||||
size_t inputLen)
|
||||
size_t inputLen)
|
||||
{
|
||||
unsigned int i, index, partLen;
|
||||
|
||||
@ -127,7 +127,7 @@ void MD5_native::update(unsigned char *input,
|
||||
// Update number of bits
|
||||
if ((count[0] += (static_cast<uint32_t>(inputLen) << 3)) <
|
||||
(static_cast<uint32_t>(inputLen) << 3))
|
||||
count[1]++;
|
||||
count[1]++;
|
||||
count[1] += (static_cast<uint32_t>(inputLen) >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
@ -135,16 +135,16 @@ void MD5_native::update(unsigned char *input,
|
||||
// Transform as many times as possible.
|
||||
|
||||
if (inputLen >= partLen) {
|
||||
memcpy(&buffer[index], input, partLen);
|
||||
transform(state, buffer);
|
||||
memcpy(&buffer[index], input, partLen);
|
||||
transform(state, buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
transform(state, &input[i]);
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
transform(state, &input[i]);
|
||||
|
||||
index = 0;
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
i = 0;
|
||||
|
||||
// Buffer remaining input
|
||||
memcpy(&buffer[index], &input[i], inputLen-i);
|
||||
@ -156,7 +156,7 @@ void MD5_native::finalize()
|
||||
{
|
||||
if (finalized)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char bits[8];
|
||||
@ -286,10 +286,10 @@ void MD5_native::encode(unsigned char *output, uint32_t *input, size_t len)
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = static_cast<unsigned char>(input[i] & 0xff);
|
||||
output[j+1] = static_cast<unsigned char>((input[i] >> 8) & 0xff);
|
||||
output[j+2] = static_cast<unsigned char>((input[i] >> 16) & 0xff);
|
||||
output[j+3] = static_cast<unsigned char>((input[i] >> 24) & 0xff);
|
||||
output[j] = static_cast<unsigned char>(input[i] & 0xff);
|
||||
output[j+1] = static_cast<unsigned char>((input[i] >> 8) & 0xff);
|
||||
output[j+2] = static_cast<unsigned char>((input[i] >> 16) & 0xff);
|
||||
output[j+3] = static_cast<unsigned char>((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,9 +300,9 @@ void MD5_native::decode(uint32_t *output, unsigned char *input, size_t len)
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] =
|
||||
output[i] =
|
||||
static_cast<uint32_t>(input[j]) |
|
||||
(static_cast<uint32_t>(input[j+1]) << 8) |
|
||||
(static_cast<uint32_t>(input[j+2]) << 16) |
|
||||
(static_cast<uint32_t>(input[j+2]) << 16) |
|
||||
(static_cast<uint32_t>(input[j+3]) << 24);
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ Pipeline::getNext(bool allow_null)
|
||||
{
|
||||
if ((this->next == 0) && (! allow_null))
|
||||
{
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pipeline::getNext() called on pipeline with no next");
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pipeline::getNext() called on pipeline with no next");
|
||||
}
|
||||
return this->next;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
bool Pl_AES_PDF::use_static_iv = false;
|
||||
|
||||
Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
|
||||
bool encrypt, unsigned char const* key,
|
||||
bool encrypt, unsigned char const* key,
|
||||
size_t key_bytes) :
|
||||
Pipeline(identifier, next),
|
||||
crypto(QPDFCryptoProvider::getImpl()),
|
||||
@ -81,17 +81,17 @@ Pl_AES_PDF::write(unsigned char* data, size_t len)
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
if (this->offset == this->buf_size)
|
||||
{
|
||||
flush(false);
|
||||
}
|
||||
if (this->offset == this->buf_size)
|
||||
{
|
||||
flush(false);
|
||||
}
|
||||
|
||||
size_t available = this->buf_size - this->offset;
|
||||
size_t bytes = (bytes_left < available ? bytes_left : available);
|
||||
bytes_left -= bytes;
|
||||
std::memcpy(this->inbuf + this->offset, p, bytes);
|
||||
this->offset += bytes;
|
||||
p += bytes;
|
||||
size_t available = this->buf_size - this->offset;
|
||||
size_t bytes = (bytes_left < available ? bytes_left : available);
|
||||
bytes_left -= bytes;
|
||||
std::memcpy(this->inbuf + this->offset, p, bytes);
|
||||
this->offset += bytes;
|
||||
p += bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,10 +100,10 @@ Pl_AES_PDF::finish()
|
||||
{
|
||||
if (this->encrypt)
|
||||
{
|
||||
if (this->offset == this->buf_size)
|
||||
{
|
||||
flush(false);
|
||||
}
|
||||
if (this->offset == this->buf_size)
|
||||
{
|
||||
flush(false);
|
||||
}
|
||||
if (! this->disable_padding)
|
||||
{
|
||||
// Pad as described in section 3.5.1 of version 1.7 of the PDF
|
||||
@ -118,19 +118,19 @@ Pl_AES_PDF::finish()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->offset != this->buf_size)
|
||||
{
|
||||
// This is never supposed to happen as the output is
|
||||
// always supposed to be padded. However, we have
|
||||
// encountered files for which the output is not a
|
||||
// multiple of the block size. In this case, pad with
|
||||
// zeroes and hope for the best.
|
||||
assert(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);
|
||||
if (this->offset != this->buf_size)
|
||||
{
|
||||
// This is never supposed to happen as the output is
|
||||
// always supposed to be padded. However, we have
|
||||
// encountered files for which the output is not a
|
||||
// multiple of the block size. In this case, pad with
|
||||
// zeroes and hope for the best.
|
||||
assert(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);
|
||||
}
|
||||
this->crypto->rijndael_finalize();
|
||||
getNext()->finish();
|
||||
@ -141,10 +141,10 @@ Pl_AES_PDF::initializeVector()
|
||||
{
|
||||
if (use_zero_iv)
|
||||
{
|
||||
for (unsigned int i = 0; i < this->buf_size; ++i)
|
||||
{
|
||||
this->cbc_block[i] = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < this->buf_size; ++i)
|
||||
{
|
||||
this->cbc_block[i] = 0;
|
||||
}
|
||||
}
|
||||
else if (use_specified_iv)
|
||||
{
|
||||
@ -152,10 +152,10 @@ Pl_AES_PDF::initializeVector()
|
||||
}
|
||||
else if (use_static_iv)
|
||||
{
|
||||
for (unsigned int i = 0; i < this->buf_size; ++i)
|
||||
{
|
||||
this->cbc_block[i] = static_cast<unsigned char>(14U * (1U + i));
|
||||
}
|
||||
for (unsigned int i = 0; i < this->buf_size; ++i)
|
||||
{
|
||||
this->cbc_block[i] = static_cast<unsigned char>(14U * (1U + i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -170,35 +170,35 @@ Pl_AES_PDF::flush(bool strip_padding)
|
||||
|
||||
if (first)
|
||||
{
|
||||
first = false;
|
||||
first = false;
|
||||
bool return_after_init = false;
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
if (encrypt)
|
||||
{
|
||||
// Set cbc_block to the initialization vector, and if
|
||||
// not zero, write it to the output stream.
|
||||
initializeVector();
|
||||
if (this->cbc_mode)
|
||||
{
|
||||
if (encrypt)
|
||||
{
|
||||
// Set cbc_block to the initialization vector, and if
|
||||
// not zero, write it to the output stream.
|
||||
initializeVector();
|
||||
if (! (this->use_zero_iv || this->use_specified_iv))
|
||||
{
|
||||
getNext()->write(this->cbc_block, this->buf_size);
|
||||
}
|
||||
}
|
||||
else if (this->use_zero_iv || this->use_specified_iv)
|
||||
}
|
||||
else if (this->use_zero_iv || this->use_specified_iv)
|
||||
{
|
||||
// Initialize vector with zeroes; zero vector was not
|
||||
// written to the beginning of the input file.
|
||||
initializeVector();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Take the first block of input as the initialization
|
||||
// vector. There's nothing to write at this time.
|
||||
memcpy(this->cbc_block, this->inbuf, this->buf_size);
|
||||
this->offset = 0;
|
||||
{
|
||||
// Take the first block of input as the initialization
|
||||
// vector. There's nothing to write at this time.
|
||||
memcpy(this->cbc_block, this->inbuf, this->buf_size);
|
||||
this->offset = 0;
|
||||
return_after_init = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this->crypto->rijndael_init(
|
||||
encrypt, this->key.get(), key_bytes,
|
||||
this->cbc_mode, this->cbc_block);
|
||||
@ -212,23 +212,23 @@ Pl_AES_PDF::flush(bool strip_padding)
|
||||
unsigned int bytes = this->buf_size;
|
||||
if (strip_padding)
|
||||
{
|
||||
unsigned char last = this->outbuf[this->buf_size - 1];
|
||||
if (last <= this->buf_size)
|
||||
{
|
||||
bool strip = true;
|
||||
for (unsigned int i = 1; i <= last; ++i)
|
||||
{
|
||||
if (this->outbuf[this->buf_size - i] != last)
|
||||
{
|
||||
strip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strip)
|
||||
{
|
||||
bytes -= last;
|
||||
}
|
||||
}
|
||||
unsigned char last = this->outbuf[this->buf_size - 1];
|
||||
if (last <= this->buf_size)
|
||||
{
|
||||
bool strip = true;
|
||||
for (unsigned int i = 1; i <= last; ++i)
|
||||
{
|
||||
if (this->outbuf[this->buf_size - i] != last)
|
||||
{
|
||||
strip = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (strip)
|
||||
{
|
||||
bytes -= last;
|
||||
}
|
||||
}
|
||||
}
|
||||
this->offset = 0;
|
||||
getNext()->write(this->outbuf, bytes);
|
||||
|
@ -21,77 +21,77 @@ Pl_ASCII85Decoder::write(unsigned char* buf, size_t len)
|
||||
{
|
||||
if (eod > 1)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (eod > 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (eod == 1)
|
||||
{
|
||||
if (buf[i] == '>')
|
||||
{
|
||||
flush();
|
||||
eod = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"broken end-of-data sequence in base 85 data");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (buf[i])
|
||||
{
|
||||
case ' ':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder ignore space");
|
||||
// ignore whitespace
|
||||
break;
|
||||
if (eod > 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (eod == 1)
|
||||
{
|
||||
if (buf[i] == '>')
|
||||
{
|
||||
flush();
|
||||
eod = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"broken end-of-data sequence in base 85 data");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (buf[i])
|
||||
{
|
||||
case ' ':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder ignore space");
|
||||
// ignore whitespace
|
||||
break;
|
||||
|
||||
case '~':
|
||||
eod = 1;
|
||||
break;
|
||||
case '~':
|
||||
eod = 1;
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
if (pos != 0)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"unexpected z during base 85 decode");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
|
||||
case 'z':
|
||||
if (pos != 0)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"unexpected z during base 85 decode");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
|
||||
unsigned char zeroes[4];
|
||||
memset(zeroes, '\0', 4);
|
||||
getNext()->write(zeroes, 4);
|
||||
}
|
||||
break;
|
||||
getNext()->write(zeroes, 4);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((buf[i] < 33) || (buf[i] > 117))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"character out of range during base 85 decode");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->inbuf[this->pos++] = buf[i];
|
||||
if (pos == 5)
|
||||
{
|
||||
flush();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
if ((buf[i] < 33) || (buf[i] > 117))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"character out of range during base 85 decode");
|
||||
}
|
||||
else
|
||||
{
|
||||
this->inbuf[this->pos++] = buf[i];
|
||||
if (pos == 5)
|
||||
{
|
||||
flush();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,26 +100,26 @@ Pl_ASCII85Decoder::flush()
|
||||
{
|
||||
if (this->pos == 0)
|
||||
{
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder no-op flush");
|
||||
return;
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder no-op flush");
|
||||
return;
|
||||
}
|
||||
unsigned long lval = 0;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
lval *= 85;
|
||||
lval += (this->inbuf[i] - 33U);
|
||||
lval *= 85;
|
||||
lval += (this->inbuf[i] - 33U);
|
||||
}
|
||||
|
||||
unsigned char outbuf[4];
|
||||
memset(outbuf, 0, 4);
|
||||
for (int i = 3; i >= 0; --i)
|
||||
{
|
||||
outbuf[i] = lval & 0xff;
|
||||
lval >>= 8;
|
||||
outbuf[i] = lval & 0xff;
|
||||
lval >>= 8;
|
||||
}
|
||||
|
||||
QTC::TC("libtests", "Pl_ASCII85Decoder partial flush",
|
||||
(this->pos == 5) ? 0 : 1);
|
||||
(this->pos == 5) ? 0 : 1);
|
||||
// Reset before calling getNext()->write in case that throws an
|
||||
// exception.
|
||||
auto t = this->pos - 1;
|
||||
|
@ -24,53 +24,53 @@ Pl_ASCIIHexDecoder::write(unsigned char* buf, size_t len)
|
||||
{
|
||||
if (this->eod)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
char ch = static_cast<char>(toupper(buf[i]));
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder ignore space");
|
||||
// ignore whitespace
|
||||
break;
|
||||
char ch = static_cast<char>(toupper(buf[i]));
|
||||
switch (ch)
|
||||
{
|
||||
case ' ':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder ignore space");
|
||||
// ignore whitespace
|
||||
break;
|
||||
|
||||
case '>':
|
||||
this->eod = true;
|
||||
flush();
|
||||
break;
|
||||
case '>':
|
||||
this->eod = true;
|
||||
flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch <= 'F')))
|
||||
{
|
||||
this->inbuf[this->pos++] = ch;
|
||||
if (this->pos == 2)
|
||||
{
|
||||
flush();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char t[2];
|
||||
t[0] = ch;
|
||||
t[1] = 0;
|
||||
throw std::runtime_error(
|
||||
std::string("character out of range"
|
||||
" during base Hex decode: ") + t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (this->eod)
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch <= 'F')))
|
||||
{
|
||||
this->inbuf[this->pos++] = ch;
|
||||
if (this->pos == 2)
|
||||
{
|
||||
flush();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char t[2];
|
||||
t[0] = ch;
|
||||
t[1] = 0;
|
||||
throw std::runtime_error(
|
||||
std::string("character out of range"
|
||||
" during base Hex decode: ") + t);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (this->eod)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,25 +79,25 @@ Pl_ASCIIHexDecoder::flush()
|
||||
{
|
||||
if (this->pos == 0)
|
||||
{
|
||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
|
||||
return;
|
||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
|
||||
return;
|
||||
}
|
||||
int b[2];
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (this->inbuf[i] >= 'A')
|
||||
{
|
||||
b[i] = this->inbuf[i] - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
b[i] = this->inbuf[i] - '0';
|
||||
}
|
||||
if (this->inbuf[i] >= 'A')
|
||||
{
|
||||
b[i] = this->inbuf[i] - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
b[i] = this->inbuf[i] - '0';
|
||||
}
|
||||
}
|
||||
unsigned char ch = static_cast<unsigned char>((b[0] << 4) + b[1]);
|
||||
|
||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush",
|
||||
(this->pos == 2) ? 0 : 1);
|
||||
(this->pos == 2) ? 0 : 1);
|
||||
// Reset before calling getNext()->write in case that throws an
|
||||
// exception.
|
||||
this->pos = 0;
|
||||
|
@ -51,7 +51,7 @@ Pl_Buffer::write(unsigned char* buf, size_t len)
|
||||
|
||||
if (getNext(true))
|
||||
{
|
||||
getNext()->write(buf, len);
|
||||
getNext()->write(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ Pl_Buffer::finish()
|
||||
this->m->ready = true;
|
||||
if (getNext(true))
|
||||
{
|
||||
getNext()->finish();
|
||||
getNext()->finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +70,7 @@ Pl_Buffer::getBuffer()
|
||||
{
|
||||
if (! this->m->ready)
|
||||
{
|
||||
throw std::logic_error("Pl_Buffer::getBuffer() called when not ready");
|
||||
throw std::logic_error("Pl_Buffer::getBuffer() called when not ready");
|
||||
}
|
||||
|
||||
Buffer* b = new Buffer(this->m->total_size);
|
||||
@ -94,7 +94,7 @@ Pl_Buffer::getMallocBuffer(unsigned char **buf, size_t* len)
|
||||
{
|
||||
if (! this->m->ready)
|
||||
{
|
||||
throw std::logic_error(
|
||||
throw std::logic_error(
|
||||
"Pl_Buffer::getMallocBuffer() called when not ready");
|
||||
}
|
||||
|
||||
|
@ -27,9 +27,9 @@ Pl_Count::write(unsigned char* buf, size_t len)
|
||||
{
|
||||
if (len)
|
||||
{
|
||||
this->m->count += QIntC::to_offset(len);
|
||||
this->m->last_char = buf[len - 1];
|
||||
getNext()->write(buf, len);
|
||||
this->m->count += QIntC::to_offset(len);
|
||||
this->m->last_char = buf[len - 1];
|
||||
getNext()->write(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ Pl_Flate::Members::~Members()
|
||||
}
|
||||
|
||||
Pl_Flate::Pl_Flate(char const* identifier, Pipeline* next,
|
||||
action_e action, unsigned int out_bufsize_int) :
|
||||
action_e action, unsigned int out_bufsize_int) :
|
||||
Pipeline(identifier, next),
|
||||
m(new Members(QIntC::to_size(out_bufsize_int), action))
|
||||
{
|
||||
@ -91,9 +91,9 @@ Pl_Flate::write(unsigned char* data, size_t len)
|
||||
{
|
||||
if (this->m->outbuf.get() == 0)
|
||||
{
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pl_Flate: write() called after finish() called");
|
||||
throw std::logic_error(
|
||||
this->identifier +
|
||||
": Pl_Flate: write() called after finish() called");
|
||||
}
|
||||
|
||||
// Write in chunks in case len is too big to fit in an int.
|
||||
@ -103,10 +103,10 @@ Pl_Flate::write(unsigned char* data, size_t len)
|
||||
unsigned char* buf = data;
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
|
||||
size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
|
||||
handleData(buf, bytes,
|
||||
(this->m->action == a_inflate ? Z_SYNC_FLUSH : Z_NO_FLUSH));
|
||||
bytes_left -= bytes;
|
||||
bytes_left -= bytes;
|
||||
buf += bytes;
|
||||
}
|
||||
}
|
||||
@ -126,7 +126,7 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
|
||||
|
||||
if (! this->m->initialized)
|
||||
{
|
||||
int err = Z_OK;
|
||||
int err = Z_OK;
|
||||
|
||||
// deflateInit and inflateInit are macros that use old-style
|
||||
// casts.
|
||||
@ -135,21 +135,21 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
if (this->m->action == a_deflate)
|
||||
{
|
||||
err = deflateInit(&zstream, compression_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = inflateInit(&zstream);
|
||||
}
|
||||
if (this->m->action == a_deflate)
|
||||
{
|
||||
err = deflateInit(&zstream, compression_level);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = inflateInit(&zstream);
|
||||
}
|
||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||
defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
checkError("Init", err);
|
||||
this->m->initialized = true;
|
||||
checkError("Init", err);
|
||||
this->m->initialized = true;
|
||||
}
|
||||
|
||||
int err = Z_OK;
|
||||
@ -157,14 +157,14 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
|
||||
bool done = false;
|
||||
while (! done)
|
||||
{
|
||||
if (this->m->action == a_deflate)
|
||||
{
|
||||
err = deflate(&zstream, flush);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = inflate(&zstream, flush);
|
||||
}
|
||||
if (this->m->action == a_deflate)
|
||||
{
|
||||
err = deflate(&zstream, flush);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = inflate(&zstream, flush);
|
||||
}
|
||||
if ((this->m->action == a_inflate) && (err != Z_OK) && zstream.msg &&
|
||||
(strcmp(zstream.msg, "incorrect data check") == 0))
|
||||
{
|
||||
@ -173,52 +173,52 @@ Pl_Flate::handleData(unsigned char* data, size_t len, int flush)
|
||||
// broken zlib streams without losing data.
|
||||
err = Z_STREAM_END;
|
||||
}
|
||||
switch (err)
|
||||
{
|
||||
case Z_BUF_ERROR:
|
||||
// Probably shouldn't be able to happen, but possible as a
|
||||
// boundary condition: if the last call to inflate exactly
|
||||
// filled the output buffer, it's possible that the next
|
||||
// call to inflate could have nothing to do. There are PDF
|
||||
// files in the wild that have this error (including at
|
||||
// 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.
|
||||
switch (err)
|
||||
{
|
||||
case Z_BUF_ERROR:
|
||||
// Probably shouldn't be able to happen, but possible as a
|
||||
// boundary condition: if the last call to inflate exactly
|
||||
// filled the output buffer, it's possible that the next
|
||||
// call to inflate could have nothing to do. There are PDF
|
||||
// files in the wild that have this error (including at
|
||||
// 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);
|
||||
done = true;
|
||||
break;
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case Z_STREAM_END:
|
||||
done = true;
|
||||
// fall through
|
||||
case Z_STREAM_END:
|
||||
done = true;
|
||||
// fall through
|
||||
|
||||
case Z_OK:
|
||||
{
|
||||
if ((zstream.avail_in == 0) &&
|
||||
(zstream.avail_out > 0))
|
||||
{
|
||||
// There is nothing left to read, and there was
|
||||
// sufficient buffer space to write everything we
|
||||
// needed, so we're done for now.
|
||||
done = true;
|
||||
}
|
||||
uLong ready =
|
||||
case Z_OK:
|
||||
{
|
||||
if ((zstream.avail_in == 0) &&
|
||||
(zstream.avail_out > 0))
|
||||
{
|
||||
// There is nothing left to read, and there was
|
||||
// sufficient buffer space to write everything we
|
||||
// needed, so we're done for now.
|
||||
done = true;
|
||||
}
|
||||
uLong ready =
|
||||
QIntC::to_ulong(this->m->out_bufsize - zstream.avail_out);
|
||||
if (ready > 0)
|
||||
{
|
||||
this->getNext()->write(this->m->outbuf.get(), ready);
|
||||
zstream.next_out = this->m->outbuf.get();
|
||||
zstream.avail_out = QIntC::to_uint(this->m->out_bufsize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (ready > 0)
|
||||
{
|
||||
this->getNext()->write(this->m->outbuf.get(), ready);
|
||||
zstream.next_out = this->m->outbuf.get();
|
||||
zstream.avail_out = QIntC::to_uint(this->m->out_bufsize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this->checkError("data", err);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this->checkError("data", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,50 +278,50 @@ Pl_Flate::checkError(char const* prefix, int error_code)
|
||||
z_stream& zstream = *(static_cast<z_stream*>(this->m->zdata));
|
||||
if (error_code != Z_OK)
|
||||
{
|
||||
char const* action_str =
|
||||
char const* action_str =
|
||||
(this->m->action == a_deflate ? "deflate" : "inflate");
|
||||
std::string msg =
|
||||
this->identifier + ": " + action_str + ": " + prefix + ": ";
|
||||
std::string msg =
|
||||
this->identifier + ": " + action_str + ": " + prefix + ": ";
|
||||
|
||||
if (zstream.msg)
|
||||
{
|
||||
msg += zstream.msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (error_code)
|
||||
{
|
||||
case Z_ERRNO:
|
||||
msg += "zlib system error";
|
||||
break;
|
||||
if (zstream.msg)
|
||||
{
|
||||
msg += zstream.msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (error_code)
|
||||
{
|
||||
case Z_ERRNO:
|
||||
msg += "zlib system error";
|
||||
break;
|
||||
|
||||
case Z_STREAM_ERROR:
|
||||
msg += "zlib stream error";
|
||||
break;
|
||||
case Z_STREAM_ERROR:
|
||||
msg += "zlib stream error";
|
||||
break;
|
||||
|
||||
case Z_DATA_ERROR:
|
||||
msg += "zlib data error";
|
||||
break;
|
||||
case Z_DATA_ERROR:
|
||||
msg += "zlib data error";
|
||||
break;
|
||||
|
||||
case Z_MEM_ERROR:
|
||||
msg += "zlib memory error";
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
msg += "zlib memory error";
|
||||
break;
|
||||
|
||||
case Z_BUF_ERROR:
|
||||
msg += "zlib buffer error";
|
||||
break;
|
||||
case Z_BUF_ERROR:
|
||||
msg += "zlib buffer error";
|
||||
break;
|
||||
|
||||
case Z_VERSION_ERROR:
|
||||
msg += "zlib version error";
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
msg += "zlib version error";
|
||||
break;
|
||||
|
||||
default:
|
||||
msg += std::string("zlib unknown error (") +
|
||||
QUtil::int_to_string(error_code) + ")";
|
||||
break;
|
||||
}
|
||||
}
|
||||
default:
|
||||
msg += std::string("zlib unknown error (") +
|
||||
QUtil::int_to_string(error_code) + ")";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error(msg);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
Pl_LZWDecoder::Pl_LZWDecoder(char const* identifier, Pipeline* next,
|
||||
bool early_code_change) :
|
||||
bool early_code_change) :
|
||||
Pipeline(identifier, next),
|
||||
code_size(9),
|
||||
next(0),
|
||||
@ -31,16 +31,16 @@ Pl_LZWDecoder::write(unsigned char* bytes, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
this->buf[next++] = bytes[i];
|
||||
if (this->next == 3)
|
||||
{
|
||||
this->next = 0;
|
||||
}
|
||||
this->bits_available += 8;
|
||||
if (this->bits_available >= this->code_size)
|
||||
{
|
||||
sendNextCode();
|
||||
}
|
||||
this->buf[next++] = bytes[i];
|
||||
if (this->next == 3)
|
||||
{
|
||||
this->next = 0;
|
||||
}
|
||||
this->bits_available += 8;
|
||||
if (this->bits_available >= this->code_size)
|
||||
{
|
||||
sendNextCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,8 +62,8 @@ Pl_LZWDecoder::sendNextCode()
|
||||
unsigned int bits_from_low = 0;
|
||||
if (bits_from_med > 8)
|
||||
{
|
||||
bits_from_low = bits_from_med - 8;
|
||||
bits_from_med = 8;
|
||||
bits_from_low = bits_from_med - 8;
|
||||
bits_from_med = 8;
|
||||
}
|
||||
unsigned int high_mask = (1U << bits_from_high) - 1U;
|
||||
unsigned int med_mask = 0xff - ((1U << (8 - bits_from_med)) - 1U);
|
||||
@ -73,21 +73,21 @@ Pl_LZWDecoder::sendNextCode()
|
||||
code += ((this->buf[med] & med_mask) >> (8 - bits_from_med));
|
||||
if (bits_from_low)
|
||||
{
|
||||
code <<= bits_from_low;
|
||||
code += ((this->buf[low] & low_mask) >> (8 - bits_from_low));
|
||||
this->byte_pos = low;
|
||||
this->bit_pos = bits_from_low;
|
||||
code <<= bits_from_low;
|
||||
code += ((this->buf[low] & low_mask) >> (8 - bits_from_low));
|
||||
this->byte_pos = low;
|
||||
this->bit_pos = bits_from_low;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->byte_pos = med;
|
||||
this->bit_pos = bits_from_med;
|
||||
this->byte_pos = med;
|
||||
this->bit_pos = bits_from_med;
|
||||
}
|
||||
if (this->bit_pos == 8)
|
||||
{
|
||||
this->bit_pos = 0;
|
||||
++this->byte_pos;
|
||||
this->byte_pos %= 3;
|
||||
this->bit_pos = 0;
|
||||
++this->byte_pos;
|
||||
this->byte_pos %= 3;
|
||||
}
|
||||
this->bits_available -= this->code_size;
|
||||
|
||||
@ -100,18 +100,18 @@ Pl_LZWDecoder::getFirstChar(unsigned int code)
|
||||
unsigned char result = '\0';
|
||||
if (code < 256)
|
||||
{
|
||||
result = static_cast<unsigned char>(code);
|
||||
result = static_cast<unsigned char>(code);
|
||||
}
|
||||
else if (code > 257)
|
||||
{
|
||||
unsigned int idx = code - 258;
|
||||
if (idx >= table.size())
|
||||
unsigned int idx = code - 258;
|
||||
if (idx >= table.size())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::getFirstChar: table overflow");
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
result = b.getBuffer()[0];
|
||||
Buffer& b = table.at(idx);
|
||||
result = b.getBuffer()[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -131,21 +131,21 @@ Pl_LZWDecoder::addToTable(unsigned char next)
|
||||
|
||||
if (this->last_code < 256)
|
||||
{
|
||||
tmp[0] = static_cast<unsigned char>(this->last_code);
|
||||
last_data = tmp;
|
||||
last_size = 1;
|
||||
tmp[0] = static_cast<unsigned char>(this->last_code);
|
||||
last_data = tmp;
|
||||
last_size = 1;
|
||||
}
|
||||
else if (this->last_code > 257)
|
||||
{
|
||||
unsigned int idx = this->last_code - 258;
|
||||
if (idx >= table.size())
|
||||
unsigned int idx = this->last_code - 258;
|
||||
if (idx >= table.size())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::addToTable: table overflow");
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
last_data = b.getBuffer();
|
||||
last_size = QIntC::to_uint(b.getSize());
|
||||
Buffer& b = table.at(idx);
|
||||
last_data = b.getBuffer();
|
||||
last_size = QIntC::to_uint(b.getSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -166,88 +166,88 @@ Pl_LZWDecoder::handleCode(unsigned int code)
|
||||
{
|
||||
if (this->eod)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (code == 256)
|
||||
{
|
||||
if (! this->table.empty())
|
||||
{
|
||||
QTC::TC("libtests", "Pl_LZWDecoder intermediate reset");
|
||||
}
|
||||
this->table.clear();
|
||||
this->code_size = 9;
|
||||
if (! this->table.empty())
|
||||
{
|
||||
QTC::TC("libtests", "Pl_LZWDecoder intermediate reset");
|
||||
}
|
||||
this->table.clear();
|
||||
this->code_size = 9;
|
||||
}
|
||||
else if (code == 257)
|
||||
{
|
||||
this->eod = true;
|
||||
this->eod = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->last_code != 256)
|
||||
{
|
||||
// Add to the table from last time. New table entry would
|
||||
// be what we read last plus the first character of what
|
||||
// we're reading now.
|
||||
unsigned char next = '\0';
|
||||
unsigned int table_size = QIntC::to_uint(table.size());
|
||||
if (code < 256)
|
||||
{
|
||||
// just read < 256; last time's next was code
|
||||
next = static_cast<unsigned char>(code);
|
||||
}
|
||||
else if (code > 257)
|
||||
{
|
||||
size_t idx = code - 258;
|
||||
if (idx > table_size)
|
||||
{
|
||||
throw std::runtime_error("LZWDecoder: bad code received");
|
||||
}
|
||||
else if (idx == table_size)
|
||||
{
|
||||
// The encoder would have just created this entry,
|
||||
// so the first character of this entry would have
|
||||
// been the same as the first character of the
|
||||
// last entry.
|
||||
QTC::TC("libtests", "Pl_LZWDecoder last was table size");
|
||||
next = getFirstChar(this->last_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
next = getFirstChar(code);
|
||||
}
|
||||
}
|
||||
unsigned int new_idx = 258 + table_size;
|
||||
if (new_idx == 4096)
|
||||
{
|
||||
throw std::runtime_error("LZWDecoder: table full");
|
||||
}
|
||||
addToTable(next);
|
||||
unsigned int change_idx = new_idx + code_change_delta;
|
||||
if ((change_idx == 511) ||
|
||||
(change_idx == 1023) ||
|
||||
(change_idx == 2047))
|
||||
{
|
||||
++this->code_size;
|
||||
}
|
||||
}
|
||||
if (this->last_code != 256)
|
||||
{
|
||||
// Add to the table from last time. New table entry would
|
||||
// be what we read last plus the first character of what
|
||||
// we're reading now.
|
||||
unsigned char next = '\0';
|
||||
unsigned int table_size = QIntC::to_uint(table.size());
|
||||
if (code < 256)
|
||||
{
|
||||
// just read < 256; last time's next was code
|
||||
next = static_cast<unsigned char>(code);
|
||||
}
|
||||
else if (code > 257)
|
||||
{
|
||||
size_t idx = code - 258;
|
||||
if (idx > table_size)
|
||||
{
|
||||
throw std::runtime_error("LZWDecoder: bad code received");
|
||||
}
|
||||
else if (idx == table_size)
|
||||
{
|
||||
// The encoder would have just created this entry,
|
||||
// so the first character of this entry would have
|
||||
// been the same as the first character of the
|
||||
// last entry.
|
||||
QTC::TC("libtests", "Pl_LZWDecoder last was table size");
|
||||
next = getFirstChar(this->last_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
next = getFirstChar(code);
|
||||
}
|
||||
}
|
||||
unsigned int new_idx = 258 + table_size;
|
||||
if (new_idx == 4096)
|
||||
{
|
||||
throw std::runtime_error("LZWDecoder: table full");
|
||||
}
|
||||
addToTable(next);
|
||||
unsigned int change_idx = new_idx + code_change_delta;
|
||||
if ((change_idx == 511) ||
|
||||
(change_idx == 1023) ||
|
||||
(change_idx == 2047))
|
||||
{
|
||||
++this->code_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (code < 256)
|
||||
{
|
||||
unsigned char ch = static_cast<unsigned char>(code);
|
||||
getNext()->write(&ch, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (code < 256)
|
||||
{
|
||||
unsigned char ch = static_cast<unsigned char>(code);
|
||||
getNext()->write(&ch, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int idx = code - 258;
|
||||
if (idx >= table.size())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Pl_LZWDecoder::handleCode: table overflow");
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
getNext()->write(b.getBuffer(), b.getSize());
|
||||
}
|
||||
Buffer& b = table.at(idx);
|
||||
getNext()->write(b.getBuffer(), b.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
this->last_code = code;
|
||||
|
@ -70,8 +70,8 @@ Pl_MD5::getHexDigest()
|
||||
{
|
||||
if (! this->enabled)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"digest requested for a disabled MD5 Pipeline");
|
||||
throw std::logic_error(
|
||||
"digest requested for a disabled MD5 Pipeline");
|
||||
}
|
||||
this->in_progress = false;
|
||||
return this->md5.unparse();
|
||||
|
@ -13,7 +13,7 @@ static int abs_diff(int a, int b)
|
||||
}
|
||||
|
||||
Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next,
|
||||
action_e action, unsigned int columns,
|
||||
action_e action, unsigned int columns,
|
||||
unsigned int samples_per_pixel,
|
||||
unsigned int bits_per_sample) :
|
||||
Pipeline(identifier, next),
|
||||
@ -74,24 +74,24 @@ Pl_PNGFilter::write(unsigned char* data, size_t len)
|
||||
size_t offset = 0;
|
||||
while (len >= left)
|
||||
{
|
||||
// finish off current row
|
||||
memcpy(this->cur_row + this->pos, data + offset, left);
|
||||
offset += left;
|
||||
len -= left;
|
||||
// finish off current row
|
||||
memcpy(this->cur_row + this->pos, data + offset, left);
|
||||
offset += left;
|
||||
len -= left;
|
||||
|
||||
processRow();
|
||||
processRow();
|
||||
|
||||
// Swap rows
|
||||
unsigned char* t = this->prev_row;
|
||||
this->prev_row = this->cur_row;
|
||||
this->cur_row = t ? t : this->buf2.get();
|
||||
memset(this->cur_row, 0, this->bytes_per_row + 1);
|
||||
left = this->incoming;
|
||||
this->pos = 0;
|
||||
// Swap rows
|
||||
unsigned char* t = this->prev_row;
|
||||
this->prev_row = this->cur_row;
|
||||
this->cur_row = t ? t : this->buf2.get();
|
||||
memset(this->cur_row, 0, this->bytes_per_row + 1);
|
||||
left = this->incoming;
|
||||
this->pos = 0;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
memcpy(this->cur_row + this->pos, data + offset, len);
|
||||
memcpy(this->cur_row + this->pos, data + offset, len);
|
||||
}
|
||||
this->pos += len;
|
||||
}
|
||||
@ -101,11 +101,11 @@ Pl_PNGFilter::processRow()
|
||||
{
|
||||
if (this->action == a_encode)
|
||||
{
|
||||
encodeRow();
|
||||
encodeRow();
|
||||
}
|
||||
else
|
||||
{
|
||||
decodeRow();
|
||||
decodeRow();
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,16 +250,16 @@ 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>(
|
||||
for (unsigned int i = 0; i < this->bytes_per_row; ++i)
|
||||
{
|
||||
ch = static_cast<unsigned char>(
|
||||
this->cur_row[i] - this->prev_row[i]);
|
||||
getNext()->write(&ch, 1);
|
||||
}
|
||||
getNext()->write(&ch, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getNext()->write(this->cur_row, this->bytes_per_row);
|
||||
getNext()->write(this->cur_row, this->bytes_per_row);
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,8 +268,8 @@ Pl_PNGFilter::finish()
|
||||
{
|
||||
if (this->pos)
|
||||
{
|
||||
// write partial row
|
||||
processRow();
|
||||
// write partial row
|
||||
processRow();
|
||||
}
|
||||
this->prev_row = 0;
|
||||
this->cur_row = buf1.get();
|
||||
|
@ -52,7 +52,7 @@ Pl_QPDFTokenizer::finish()
|
||||
QPDFTokenizer::Token token = this->m->tokenizer.readToken(
|
||||
input, "offset " + QUtil::int_to_string(input->tell()),
|
||||
true);
|
||||
this->m->filter->handleToken(token);
|
||||
this->m->filter->handleToken(token);
|
||||
if (token.getType() == QPDFTokenizer::tt_eof)
|
||||
{
|
||||
break;
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
Pl_RC4::Pl_RC4(char const* identifier, Pipeline* next,
|
||||
unsigned char const* key_data, int key_len,
|
||||
size_t out_bufsize) :
|
||||
unsigned char const* key_data, int key_len,
|
||||
size_t out_bufsize) :
|
||||
Pipeline(identifier, next),
|
||||
out_bufsize(out_bufsize),
|
||||
rc4(key_data, key_len)
|
||||
@ -21,9 +21,9 @@ Pl_RC4::write(unsigned char* data, size_t len)
|
||||
{
|
||||
if (this->outbuf.get() == 0)
|
||||
{
|
||||
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;
|
||||
@ -31,13 +31,13 @@ Pl_RC4::write(unsigned char* data, size_t len)
|
||||
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
size_t bytes =
|
||||
size_t bytes =
|
||||
(bytes_left < this->out_bufsize ? bytes_left : out_bufsize);
|
||||
bytes_left -= bytes;
|
||||
bytes_left -= bytes;
|
||||
// lgtm[cpp/weak-cryptographic-algorithm]
|
||||
rc4.process(p, bytes, outbuf.get());
|
||||
p += bytes;
|
||||
getNext()->write(outbuf.get(), bytes);
|
||||
rc4.process(p, bytes, outbuf.get());
|
||||
p += bytes;
|
||||
getNext()->write(outbuf.get(), bytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ Pl_SHA2::write(unsigned char* buf, size_t len)
|
||||
{
|
||||
if (! this->in_progress)
|
||||
{
|
||||
this->in_progress = true;
|
||||
this->in_progress = true;
|
||||
}
|
||||
|
||||
// Write in chunks in case len is too big to fit in an int.
|
||||
@ -35,9 +35,9 @@ Pl_SHA2::write(unsigned char* buf, size_t len)
|
||||
unsigned char* data = buf;
|
||||
while (bytes_left > 0)
|
||||
{
|
||||
size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
|
||||
size_t bytes = (bytes_left >= max_bytes ? max_bytes : bytes_left);
|
||||
this->crypto->SHA2_update(data, bytes);
|
||||
bytes_left -= bytes;
|
||||
bytes_left -= bytes;
|
||||
data += bytes;
|
||||
}
|
||||
|
||||
@ -63,8 +63,8 @@ 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);
|
||||
@ -75,8 +75,8 @@ 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();
|
||||
}
|
||||
@ -86,8 +86,8 @@ 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());
|
||||
}
|
||||
|
@ -31,17 +31,17 @@ Pl_StdioFile::write(unsigned char* buf, size_t len)
|
||||
size_t so_far = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
so_far = fwrite(buf, 1, len, this->m->file);
|
||||
if (so_far == 0)
|
||||
{
|
||||
QUtil::throw_system_error(
|
||||
this->identifier + ": Pl_StdioFile::write");
|
||||
}
|
||||
else
|
||||
{
|
||||
buf += so_far;
|
||||
len -= so_far;
|
||||
}
|
||||
so_far = fwrite(buf, 1, len, this->m->file);
|
||||
if (so_far == 0)
|
||||
{
|
||||
QUtil::throw_system_error(
|
||||
this->identifier + ": Pl_StdioFile::write");
|
||||
}
|
||||
else
|
||||
{
|
||||
buf += so_far;
|
||||
len -= so_far;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,8 +51,8 @@ Pl_StdioFile::finish()
|
||||
if ((fflush(this->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");
|
||||
}
|
||||
}
|
||||
|
@ -56,21 +56,21 @@ Pl_TIFFPredictor::write(unsigned char* data, size_t len)
|
||||
size_t offset = 0;
|
||||
while (len >= left)
|
||||
{
|
||||
// finish off current row
|
||||
memcpy(this->cur_row.get() + this->pos, data + offset, left);
|
||||
offset += left;
|
||||
len -= left;
|
||||
// finish off current row
|
||||
memcpy(this->cur_row.get() + this->pos, data + offset, left);
|
||||
offset += left;
|
||||
len -= left;
|
||||
|
||||
processRow();
|
||||
processRow();
|
||||
|
||||
// Prepare for next row
|
||||
memset(this->cur_row.get(), 0, this->bytes_per_row);
|
||||
left = this->bytes_per_row;
|
||||
this->pos = 0;
|
||||
// Prepare for next row
|
||||
memset(this->cur_row.get(), 0, this->bytes_per_row);
|
||||
left = this->bytes_per_row;
|
||||
this->pos = 0;
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
memcpy(this->cur_row.get() + this->pos, data + offset, len);
|
||||
memcpy(this->cur_row.get() + this->pos, data + offset, len);
|
||||
}
|
||||
this->pos += len;
|
||||
}
|
||||
@ -116,8 +116,8 @@ Pl_TIFFPredictor::finish()
|
||||
{
|
||||
if (this->pos)
|
||||
{
|
||||
// write partial row
|
||||
processRow();
|
||||
// write partial row
|
||||
processRow();
|
||||
}
|
||||
this->pos = 0;
|
||||
memset(this->cur_row.get(), 0, this->bytes_per_row);
|
||||
|
1312
libqpdf/QPDF.cc
1312
libqpdf/QPDF.cc
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@ QPDFArgParser::Members::Members(
|
||||
// Remove prefix added by libtool for consistency during testing.
|
||||
if (strncmp(p, "lt-", 3) == 0)
|
||||
{
|
||||
p += 3;
|
||||
p += 3;
|
||||
}
|
||||
whoami = p;
|
||||
}
|
||||
|
@ -20,11 +20,11 @@ QPDFCrypto_gnutls::~QPDFCrypto_gnutls()
|
||||
{
|
||||
if (this->hash_ctx)
|
||||
{
|
||||
gnutls_hash_deinit(this->hash_ctx, digest);
|
||||
gnutls_hash_deinit(this->hash_ctx, digest);
|
||||
}
|
||||
if (cipher_ctx)
|
||||
{
|
||||
gnutls_cipher_deinit(this->cipher_ctx);
|
||||
gnutls_cipher_deinit(this->cipher_ctx);
|
||||
}
|
||||
this->aes_key_data = nullptr;
|
||||
this->aes_key_len = 0;
|
||||
@ -36,8 +36,8 @@ QPDFCrypto_gnutls::provideRandomData(unsigned char* data, size_t len)
|
||||
int code = gnutls_rnd (GNUTLS_RND_KEY, data, len);
|
||||
if (code < 0)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: random number generation error: ") +
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: random number generation error: ") +
|
||||
std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
@ -50,8 +50,8 @@ QPDFCrypto_gnutls::MD5_init()
|
||||
if (code < 0)
|
||||
{
|
||||
this->hash_ctx = nullptr;
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: MD5 error: ") +
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: MD5 error: ") +
|
||||
std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
@ -84,7 +84,7 @@ QPDFCrypto_gnutls::RC4_init(unsigned char const* key_data, int key_len)
|
||||
RC4_finalize();
|
||||
if (key_len == -1)
|
||||
{
|
||||
key_len = QIntC::to_int(
|
||||
key_len = QIntC::to_int(
|
||||
strlen(reinterpret_cast<char const*>(key_data)));
|
||||
}
|
||||
gnutls_datum_t key;
|
||||
@ -96,8 +96,8 @@ QPDFCrypto_gnutls::RC4_init(unsigned char const* key_data, int key_len)
|
||||
if (code < 0)
|
||||
{
|
||||
this->cipher_ctx = nullptr;
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: RC4 error: ") +
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: RC4 error: ") +
|
||||
std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
@ -118,8 +118,8 @@ QPDFCrypto_gnutls::RC4_finalize()
|
||||
{
|
||||
if (this->cipher_ctx)
|
||||
{
|
||||
gnutls_cipher_deinit(this->cipher_ctx);
|
||||
this->cipher_ctx = nullptr;
|
||||
gnutls_cipher_deinit(this->cipher_ctx);
|
||||
this->cipher_ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,8 +148,8 @@ QPDFCrypto_gnutls::SHA2_init(int bits)
|
||||
if (code < 0)
|
||||
{
|
||||
this->hash_ctx = nullptr;
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: SHA") + QUtil::int_to_string(bits) +
|
||||
throw std::runtime_error(
|
||||
std::string("gnutls: SHA") + QUtil::int_to_string(bits) +
|
||||
" error: " + std::string(gnutls_strerror(code)));
|
||||
}
|
||||
}
|
||||
@ -278,8 +278,8 @@ QPDFCrypto_gnutls::rijndael_finalize()
|
||||
{
|
||||
if (this->cipher_ctx)
|
||||
{
|
||||
gnutls_cipher_deinit(this->cipher_ctx);
|
||||
this->cipher_ctx = nullptr;
|
||||
gnutls_cipher_deinit(this->cipher_ctx);
|
||||
this->cipher_ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
QPDFExc::QPDFExc(qpdf_error_code_e error_code,
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message) :
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message) :
|
||||
std::runtime_error(createWhat(filename, object, offset, message)),
|
||||
error_code(error_code),
|
||||
filename(filename),
|
||||
@ -18,14 +18,14 @@ QPDFExc::QPDFExc(qpdf_error_code_e error_code,
|
||||
|
||||
std::string
|
||||
QPDFExc::createWhat(std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message)
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message)
|
||||
{
|
||||
std::string result;
|
||||
if (! filename.empty())
|
||||
{
|
||||
result += filename;
|
||||
result += filename;
|
||||
}
|
||||
if (! (object.empty() && offset == 0))
|
||||
{
|
||||
@ -33,18 +33,18 @@ QPDFExc::createWhat(std::string const& filename,
|
||||
{
|
||||
result += " (";
|
||||
}
|
||||
if (! object.empty())
|
||||
{
|
||||
result += object;
|
||||
if (offset > 0)
|
||||
{
|
||||
result += ", ";
|
||||
}
|
||||
}
|
||||
if (offset > 0)
|
||||
{
|
||||
result += "offset " + QUtil::int_to_string(offset);
|
||||
}
|
||||
if (! object.empty())
|
||||
{
|
||||
result += object;
|
||||
if (offset > 0)
|
||||
{
|
||||
result += ", ";
|
||||
}
|
||||
}
|
||||
if (offset > 0)
|
||||
{
|
||||
result += "offset " + QUtil::int_to_string(offset);
|
||||
}
|
||||
if (! filename.empty())
|
||||
{
|
||||
result += ")";
|
||||
@ -52,7 +52,7 @@ QPDFExc::createWhat(std::string const& filename,
|
||||
}
|
||||
if (! result.empty())
|
||||
{
|
||||
result += ": ";
|
||||
result += ": ";
|
||||
}
|
||||
result += message;
|
||||
return result;
|
||||
|
@ -18,7 +18,7 @@ bool
|
||||
QPDFObjGen::operator<(QPDFObjGen const& rhs) const
|
||||
{
|
||||
return ((this->obj < rhs.obj) ||
|
||||
((this->obj == rhs.obj) && (this->gen < rhs.gen)));
|
||||
((this->obj == rhs.obj) && (this->gen < rhs.gen)));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -117,7 +117,7 @@ QPDFObjectHandle::TokenFilter::write(char const* data, size_t len)
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
this->pipeline->write(QUtil::unsigned_char_pointer(data), len);
|
||||
this->pipeline->write(QUtil::unsigned_char_pointer(data), len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,14 +241,14 @@ QPDFObjectHandle::releaseResolved()
|
||||
// destruction. See comments in QPDF::~QPDF().
|
||||
if (isIndirect())
|
||||
{
|
||||
if (this->obj.get())
|
||||
{
|
||||
this->obj = 0;
|
||||
}
|
||||
if (this->obj.get())
|
||||
{
|
||||
this->obj = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QPDFObject::ObjAccessor::releaseResolved(this->obj.get());
|
||||
QPDFObject::ObjAccessor::releaseResolved(this->obj.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,11 +304,11 @@ class QPDFObjectTypeAccessor
|
||||
public:
|
||||
static bool check(QPDFObject* o)
|
||||
{
|
||||
return (o && dynamic_cast<T*>(o));
|
||||
return (o && dynamic_cast<T*>(o));
|
||||
}
|
||||
static bool check(QPDFObject const* o)
|
||||
{
|
||||
return (o && dynamic_cast<T const*>(o));
|
||||
return (o && dynamic_cast<T const*>(o));
|
||||
}
|
||||
};
|
||||
|
||||
@ -377,11 +377,11 @@ QPDFObjectHandle::getNumericValue()
|
||||
double result = 0.0;
|
||||
if (isInteger())
|
||||
{
|
||||
result = static_cast<double>(getIntValue());
|
||||
result = static_cast<double>(getIntValue());
|
||||
}
|
||||
else if (isReal())
|
||||
{
|
||||
result = atof(getRealValue().c_str());
|
||||
result = atof(getRealValue().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1443,7 +1443,7 @@ QPDFObjectHandle::getOwningQPDF()
|
||||
|
||||
void
|
||||
QPDFObjectHandle::replaceKey(std::string const& key,
|
||||
QPDFObjectHandle value)
|
||||
QPDFObjectHandle value)
|
||||
{
|
||||
if (isDictionary())
|
||||
{
|
||||
@ -1474,7 +1474,7 @@ QPDFObjectHandle::removeKey(std::string const& key)
|
||||
|
||||
void
|
||||
QPDFObjectHandle::replaceOrRemoveKey(std::string const& key,
|
||||
QPDFObjectHandle value)
|
||||
QPDFObjectHandle value)
|
||||
{
|
||||
if (isDictionary())
|
||||
{
|
||||
@ -1548,7 +1548,7 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p, bool* filtering_attempted,
|
||||
{
|
||||
assertStream();
|
||||
return dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData(
|
||||
p, filtering_attempted, encode_flags, decode_level,
|
||||
p, filtering_attempted, encode_flags, decode_level,
|
||||
suppress_warnings, will_retry);
|
||||
}
|
||||
|
||||
@ -1561,14 +1561,14 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p,
|
||||
assertStream();
|
||||
bool filtering_attempted;
|
||||
dynamic_cast<QPDF_Stream*>(obj.get())->pipeStreamData(
|
||||
p, &filtering_attempted, encode_flags, decode_level,
|
||||
p, &filtering_attempted, encode_flags, decode_level,
|
||||
suppress_warnings, will_retry);
|
||||
return filtering_attempted;
|
||||
}
|
||||
|
||||
bool
|
||||
QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter,
|
||||
bool normalize, bool compress)
|
||||
bool normalize, bool compress)
|
||||
{
|
||||
int encode_flags = 0;
|
||||
qpdf_stream_decode_level_e decode_level = qpdf_dl_none;
|
||||
@ -1589,35 +1589,35 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p, bool filter,
|
||||
|
||||
void
|
||||
QPDFObjectHandle::replaceStreamData(PointerHolder<Buffer> data,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
{
|
||||
assertStream();
|
||||
dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
|
||||
data, filter, decode_parms);
|
||||
data, filter, decode_parms);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObjectHandle::replaceStreamData(std::string const& data,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
{
|
||||
assertStream();
|
||||
auto b = make_pointer_holder<Buffer>(data.length());
|
||||
unsigned char* bp = b->getBuffer();
|
||||
memcpy(bp, data.c_str(), data.length());
|
||||
dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
|
||||
b, filter, decode_parms);
|
||||
b, filter, decode_parms);
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObjectHandle::replaceStreamData(PointerHolder<StreamDataProvider> provider,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
{
|
||||
assertStream();
|
||||
dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
|
||||
provider, filter, decode_parms);
|
||||
provider, filter, decode_parms);
|
||||
}
|
||||
|
||||
class FunctionProvider: public QPDFObjectHandle::StreamDataProvider
|
||||
@ -1662,7 +1662,7 @@ QPDFObjectHandle::replaceStreamData(std::function<void(Pipeline*)> provider,
|
||||
auto sdp = PointerHolder<StreamDataProvider>(
|
||||
new FunctionProvider(provider));
|
||||
dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
|
||||
sdp, filter, decode_parms);
|
||||
sdp, filter, decode_parms);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1675,7 +1675,7 @@ QPDFObjectHandle::replaceStreamData(
|
||||
auto sdp = PointerHolder<StreamDataProvider>(
|
||||
new FunctionProvider(provider));
|
||||
dynamic_cast<QPDF_Stream*>(obj.get())->replaceStreamData(
|
||||
sdp, filter, decode_parms);
|
||||
sdp, filter, decode_parms);
|
||||
}
|
||||
|
||||
QPDFObjGen
|
||||
@ -1710,28 +1710,28 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
|
||||
std::vector<QPDFObjectHandle> result;
|
||||
if (isArray())
|
||||
{
|
||||
int n_items = getArrayNItems();
|
||||
for (int i = 0; i < n_items; ++i)
|
||||
{
|
||||
QPDFObjectHandle item = getArrayItem(i);
|
||||
if (item.isStream())
|
||||
int n_items = getArrayNItems();
|
||||
for (int i = 0; i < n_items; ++i)
|
||||
{
|
||||
QPDFObjectHandle item = getArrayItem(i);
|
||||
if (item.isStream())
|
||||
{
|
||||
result.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle non-stream in stream array");
|
||||
warn(item.getOwningQPDF(),
|
||||
QPDFExc(qpdf_e_damaged_pdf, description,
|
||||
"item index " + QUtil::int_to_string(i) +
|
||||
" (from 0)", 0,
|
||||
"ignoring non-stream in an array of streams"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isStream())
|
||||
{
|
||||
result.push_back(*this);
|
||||
result.push_back(*this);
|
||||
}
|
||||
else if (! isNull())
|
||||
{
|
||||
@ -1784,18 +1784,18 @@ QPDFObjectHandle::addPageContents(QPDFObjectHandle new_contents, bool first)
|
||||
std::vector<QPDFObjectHandle> content_streams;
|
||||
if (first)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle prepend page contents");
|
||||
content_streams.push_back(new_contents);
|
||||
QTC::TC("qpdf", "QPDFObjectHandle prepend page contents");
|
||||
content_streams.push_back(new_contents);
|
||||
}
|
||||
for (std::vector<QPDFObjectHandle>::iterator iter = orig_contents.begin();
|
||||
iter != orig_contents.end(); ++iter)
|
||||
iter != orig_contents.end(); ++iter)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle append page contents");
|
||||
content_streams.push_back(*iter);
|
||||
QTC::TC("qpdf", "QPDFObjectHandle append page contents");
|
||||
content_streams.push_back(*iter);
|
||||
}
|
||||
if (! first)
|
||||
{
|
||||
content_streams.push_back(new_contents);
|
||||
content_streams.push_back(new_contents);
|
||||
}
|
||||
|
||||
QPDFObjectHandle contents = QPDFObjectHandle::newArray(content_streams);
|
||||
@ -1899,12 +1899,12 @@ QPDFObjectHandle::unparse()
|
||||
std::string result;
|
||||
if (this->isIndirect())
|
||||
{
|
||||
result = QUtil::int_to_string(this->objid) + " " +
|
||||
QUtil::int_to_string(this->generation) + " R";
|
||||
result = QUtil::int_to_string(this->objid) + " " +
|
||||
QUtil::int_to_string(this->generation) + " R";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = unparseResolved();
|
||||
result = unparseResolved();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -2253,10 +2253,10 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
std::string& contents_string = contents_string_stack.back();
|
||||
qpdf_offset_t& contents_offset = contents_offset_stack.back();
|
||||
|
||||
object = QPDFObjectHandle();
|
||||
set_offset = false;
|
||||
object = QPDFObjectHandle();
|
||||
set_offset = false;
|
||||
|
||||
QPDFTokenizer::Token token =
|
||||
QPDFTokenizer::Token token =
|
||||
tokenizer.readToken(input, object_description, true);
|
||||
std::string const& token_error_message = token.getErrorMessage();
|
||||
if (! token_error_message.empty())
|
||||
@ -2269,8 +2269,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
token_error_message));
|
||||
}
|
||||
|
||||
switch (token.getType())
|
||||
{
|
||||
switch (token.getType())
|
||||
{
|
||||
case QPDFTokenizer::tt_eof:
|
||||
if (! content_stream)
|
||||
{
|
||||
@ -2286,14 +2286,14 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_bad:
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad token in parse");
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad token in parse");
|
||||
bad = true;
|
||||
object = newNull();
|
||||
break;
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_brace_open:
|
||||
case QPDFTokenizer::tt_brace_close:
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad brace");
|
||||
case QPDFTokenizer::tt_brace_open:
|
||||
case QPDFTokenizer::tt_brace_close:
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad brace");
|
||||
warn(context,
|
||||
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
object_description,
|
||||
@ -2301,16 +2301,16 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
"treating unexpected brace token as null"));
|
||||
bad = true;
|
||||
object = newNull();
|
||||
break;
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_array_close:
|
||||
if (state == st_array)
|
||||
{
|
||||
case QPDFTokenizer::tt_array_close:
|
||||
if (state == st_array)
|
||||
{
|
||||
state = st_stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad array close");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad array close");
|
||||
warn(context,
|
||||
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
object_description,
|
||||
@ -2318,17 +2318,17 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
"treating unexpected array close token as null"));
|
||||
bad = true;
|
||||
object = newNull();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_dict_close:
|
||||
if (state == st_dictionary)
|
||||
{
|
||||
case QPDFTokenizer::tt_dict_close:
|
||||
if (state == st_dictionary)
|
||||
{
|
||||
state = st_stop;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad dictionary close");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle bad dictionary close");
|
||||
warn(context,
|
||||
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
object_description,
|
||||
@ -2336,14 +2336,14 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
"unexpected dictionary close token"));
|
||||
bad = true;
|
||||
object = newNull();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_array_open:
|
||||
case QPDFTokenizer::tt_dict_open:
|
||||
case QPDFTokenizer::tt_array_open:
|
||||
case QPDFTokenizer::tt_dict_open:
|
||||
if (olist_stack.size() > 500)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle too deep");
|
||||
QTC::TC("qpdf", "QPDFObjectHandle too deep");
|
||||
warn(context,
|
||||
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
object_description,
|
||||
@ -2365,54 +2365,54 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
contents_string_stack.push_back("");
|
||||
contents_offset_stack.push_back(-1);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_bool:
|
||||
object = newBool((token.getValue() == "true"));
|
||||
break;
|
||||
case QPDFTokenizer::tt_bool:
|
||||
object = newBool((token.getValue() == "true"));
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_null:
|
||||
object = newNull();
|
||||
break;
|
||||
case QPDFTokenizer::tt_null:
|
||||
object = newNull();
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_integer:
|
||||
object = newInteger(QUtil::string_to_ll(token.getValue().c_str()));
|
||||
break;
|
||||
case QPDFTokenizer::tt_integer:
|
||||
object = newInteger(QUtil::string_to_ll(token.getValue().c_str()));
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_real:
|
||||
object = newReal(token.getValue());
|
||||
break;
|
||||
case QPDFTokenizer::tt_real:
|
||||
object = newReal(token.getValue());
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_name:
|
||||
{
|
||||
std::string name = token.getValue();
|
||||
object = newName(name);
|
||||
case QPDFTokenizer::tt_name:
|
||||
{
|
||||
std::string name = token.getValue();
|
||||
object = newName(name);
|
||||
|
||||
if (name == "/Contents")
|
||||
{
|
||||
b_contents = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
b_contents = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (name == "/Contents")
|
||||
{
|
||||
b_contents = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
b_contents = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_word:
|
||||
{
|
||||
std::string const& value = token.getValue();
|
||||
case QPDFTokenizer::tt_word:
|
||||
{
|
||||
std::string const& value = token.getValue();
|
||||
if (content_stream)
|
||||
{
|
||||
object = QPDFObjectHandle::newOperator(value);
|
||||
}
|
||||
else if ((value == "R") && (state != st_top) &&
|
||||
else if ((value == "R") && (state != st_top) &&
|
||||
(olist.size() >= 2) &&
|
||||
(! olist.at(olist.size() - 1).isIndirect()) &&
|
||||
(olist.at(olist.size() - 1).isInteger()) &&
|
||||
(! olist.at(olist.size() - 2).isIndirect()) &&
|
||||
(olist.at(olist.size() - 2).isInteger()))
|
||||
{
|
||||
{
|
||||
if (context == 0)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle indirect without context");
|
||||
@ -2420,25 +2420,25 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
"QPDFObjectHandle::parse called without context"
|
||||
" on an object with indirect references");
|
||||
}
|
||||
// Try to resolve indirect objects
|
||||
object = newIndirect(
|
||||
context,
|
||||
olist.at(olist.size() - 2).getIntValueAsInt(),
|
||||
olist.at(olist.size() - 1).getIntValueAsInt());
|
||||
olist.remove_last();
|
||||
olist.remove_last();
|
||||
}
|
||||
else if ((value == "endobj") && (state == st_top))
|
||||
{
|
||||
// We just saw endobj without having read
|
||||
// anything. Treat this as a null and do not move
|
||||
// the input source's offset.
|
||||
object = newNull();
|
||||
input->seek(input->getLastOffset(), SEEK_SET);
|
||||
// Try to resolve indirect objects
|
||||
object = newIndirect(
|
||||
context,
|
||||
olist.at(olist.size() - 2).getIntValueAsInt(),
|
||||
olist.at(olist.size() - 1).getIntValueAsInt());
|
||||
olist.remove_last();
|
||||
olist.remove_last();
|
||||
}
|
||||
else if ((value == "endobj") && (state == st_top))
|
||||
{
|
||||
// We just saw endobj without having read
|
||||
// anything. Treat this as a null and do not move
|
||||
// the input source's offset.
|
||||
object = newNull();
|
||||
input->seek(input->getLastOffset(), SEEK_SET);
|
||||
empty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle treat word as string");
|
||||
warn(context,
|
||||
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
@ -2448,13 +2448,13 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
" treating as string"));
|
||||
bad = true;
|
||||
object = newString(value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case QPDFTokenizer::tt_string:
|
||||
{
|
||||
std::string val = token.getValue();
|
||||
case QPDFTokenizer::tt_string:
|
||||
{
|
||||
std::string val = token.getValue();
|
||||
if (decrypter)
|
||||
{
|
||||
if (b_contents)
|
||||
@ -2465,12 +2465,12 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
}
|
||||
decrypter->decryptString(val);
|
||||
}
|
||||
object = QPDFObjectHandle::newString(val);
|
||||
}
|
||||
object = QPDFObjectHandle::newString(val);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
default:
|
||||
warn(context,
|
||||
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
|
||||
object_description,
|
||||
@ -2479,8 +2479,8 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
"reading object"));
|
||||
bad = true;
|
||||
object = newNull();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((! object.isInitialized()) &&
|
||||
(! ((state == st_start) ||
|
||||
@ -2656,17 +2656,17 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
|
||||
}
|
||||
dict[key] = val;
|
||||
}
|
||||
if (!contents_string.empty() &&
|
||||
dict.count("/Type") &&
|
||||
if (!contents_string.empty() &&
|
||||
dict.count("/Type") &&
|
||||
dict["/Type"].isNameAndEquals("/Sig") &&
|
||||
dict.count("/ByteRange") &&
|
||||
dict.count("/Contents") &&
|
||||
dict["/Contents"].isString())
|
||||
{
|
||||
dict["/Contents"]
|
||||
= QPDFObjectHandle::newString(contents_string);
|
||||
dict["/Contents"].setParsedOffset(contents_offset);
|
||||
}
|
||||
dict.count("/ByteRange") &&
|
||||
dict.count("/Contents") &&
|
||||
dict["/Contents"].isString())
|
||||
{
|
||||
dict["/Contents"]
|
||||
= QPDFObjectHandle::newString(contents_string);
|
||||
dict["/Contents"].setParsedOffset(contents_offset);
|
||||
}
|
||||
object = newDictionary(dict);
|
||||
setObjectDescriptionFromInput(
|
||||
object, context, object_description, input, offset);
|
||||
@ -2889,12 +2889,12 @@ QPDFObjectHandle::newDictionary(
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDFObjectHandle::newStream(QPDF* qpdf, int objid, int generation,
|
||||
QPDFObjectHandle stream_dict,
|
||||
qpdf_offset_t offset, size_t length)
|
||||
QPDFObjectHandle stream_dict,
|
||||
qpdf_offset_t offset, size_t length)
|
||||
{
|
||||
QPDFObjectHandle result = QPDFObjectHandle(new QPDF_Stream(
|
||||
qpdf, objid, generation,
|
||||
stream_dict, offset, length));
|
||||
qpdf, objid, generation,
|
||||
stream_dict, offset, length));
|
||||
if (offset)
|
||||
{
|
||||
result.setParsedOffset(offset);
|
||||
@ -2913,8 +2913,8 @@ QPDFObjectHandle::newStream(QPDF* qpdf)
|
||||
QTC::TC("qpdf", "QPDFObjectHandle newStream");
|
||||
QPDFObjectHandle stream_dict = newDictionary();
|
||||
QPDFObjectHandle result = qpdf->makeIndirectObject(
|
||||
QPDFObjectHandle(
|
||||
new QPDF_Stream(qpdf, 0, 0, stream_dict, 0, 0)));
|
||||
QPDFObjectHandle(
|
||||
new QPDF_Stream(qpdf, 0, 0, stream_dict, 0, 0)));
|
||||
result.dereference();
|
||||
QPDF_Stream* stream =
|
||||
dynamic_cast<QPDF_Stream*>(result.obj.get());
|
||||
@ -2946,7 +2946,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf)
|
||||
// Reserve a spot for this object by assigning it an object
|
||||
// number, but then return an unresolved handle to the object.
|
||||
QPDFObjectHandle reserved = qpdf->makeIndirectObject(
|
||||
QPDFObjectHandle(new QPDF_Reserved()));
|
||||
QPDFObjectHandle(new QPDF_Reserved()));
|
||||
QPDFObjectHandle result =
|
||||
newIndirect(qpdf, reserved.objid, reserved.generation);
|
||||
result.reserved = true;
|
||||
@ -3003,14 +3003,14 @@ QPDFObjectHandle::shallowCopyInternal(QPDFObjectHandle& new_obj,
|
||||
|
||||
if (isStream())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream");
|
||||
throw std::runtime_error(
|
||||
"attempt to make a shallow copy of a stream");
|
||||
QTC::TC("qpdf", "QPDFObjectHandle ERR shallow copy stream");
|
||||
throw std::runtime_error(
|
||||
"attempt to make a shallow copy of a stream");
|
||||
}
|
||||
|
||||
if (isArray())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy array");
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy array");
|
||||
// No newArray for shallow copying the sparse array
|
||||
QPDF_Array* arr = dynamic_cast<QPDF_Array*>(obj.get());
|
||||
new_obj = QPDFObjectHandle(
|
||||
@ -3018,12 +3018,12 @@ QPDFObjectHandle::shallowCopyInternal(QPDFObjectHandle& new_obj,
|
||||
}
|
||||
else if (isDictionary())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy dictionary");
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy dictionary");
|
||||
new_obj = newDictionary(getDictAsMap());
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy scalar");
|
||||
QTC::TC("qpdf", "QPDFObjectHandle shallow copy scalar");
|
||||
new_obj = *this;
|
||||
}
|
||||
|
||||
@ -3040,27 +3040,27 @@ QPDFObjectHandle::copyObject(std::set<QPDFObjGen>& visited,
|
||||
|
||||
if (isStream())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle copy stream",
|
||||
QTC::TC("qpdf", "QPDFObjectHandle copy stream",
|
||||
stop_at_streams ? 0 : 1);
|
||||
if (stop_at_streams)
|
||||
{
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error(
|
||||
"attempt to make a stream into a direct object");
|
||||
throw std::runtime_error(
|
||||
"attempt to make a stream into a direct object");
|
||||
}
|
||||
|
||||
QPDFObjGen cur_og(this->objid, this->generation);
|
||||
if (cur_og.getObj() != 0)
|
||||
{
|
||||
if (visited.count(cur_og))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle makeDirect loop");
|
||||
throw std::runtime_error(
|
||||
"loop detected while converting object from "
|
||||
"indirect to direct");
|
||||
}
|
||||
visited.insert(cur_og);
|
||||
if (visited.count(cur_og))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle makeDirect loop");
|
||||
throw std::runtime_error(
|
||||
"loop detected while converting object from "
|
||||
"indirect to direct");
|
||||
}
|
||||
visited.insert(cur_og);
|
||||
}
|
||||
|
||||
if (isReserved())
|
||||
@ -3079,42 +3079,42 @@ QPDFObjectHandle::copyObject(std::set<QPDFObjGen>& visited,
|
||||
|
||||
if (isBool())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone bool");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Bool(getBoolValue()));
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone bool");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Bool(getBoolValue()));
|
||||
}
|
||||
else if (isNull())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone null");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Null());
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone null");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Null());
|
||||
}
|
||||
else if (isInteger())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone integer");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Integer(getIntValue()));
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone integer");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Integer(getIntValue()));
|
||||
}
|
||||
else if (isReal())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone real");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Real(getRealValue()));
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone real");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Real(getRealValue()));
|
||||
}
|
||||
else if (isName())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone name");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Name(getName()));
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone name");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Name(getName()));
|
||||
}
|
||||
else if (isString())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone string");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_String(getStringValue()));
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone string");
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_String(getStringValue()));
|
||||
}
|
||||
else if (isArray())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone array");
|
||||
std::vector<QPDFObjectHandle> items;
|
||||
int n = getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
items.push_back(getArrayItem(i));
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone array");
|
||||
std::vector<QPDFObjectHandle> items;
|
||||
int n = getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
items.push_back(getArrayItem(i));
|
||||
if ((! first_level_only) &&
|
||||
(cross_indirect || (! items.back().isIndirect())))
|
||||
{
|
||||
@ -3122,18 +3122,18 @@ QPDFObjectHandle::copyObject(std::set<QPDFObjGen>& visited,
|
||||
visited, cross_indirect,
|
||||
first_level_only, stop_at_streams);
|
||||
}
|
||||
}
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Array(items));
|
||||
}
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Array(items));
|
||||
}
|
||||
else if (isDictionary())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone dictionary");
|
||||
std::set<std::string> keys = getKeys();
|
||||
std::map<std::string, QPDFObjectHandle> items;
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
items[*iter] = getKey(*iter);
|
||||
QTC::TC("qpdf", "QPDFObjectHandle clone dictionary");
|
||||
std::set<std::string> keys = getKeys();
|
||||
std::map<std::string, QPDFObjectHandle> items;
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
items[*iter] = getKey(*iter);
|
||||
if ((! first_level_only) &&
|
||||
(cross_indirect || (! items[*iter].isIndirect())))
|
||||
{
|
||||
@ -3141,20 +3141,20 @@ QPDFObjectHandle::copyObject(std::set<QPDFObjGen>& visited,
|
||||
visited, cross_indirect,
|
||||
first_level_only, stop_at_streams);
|
||||
}
|
||||
}
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Dictionary(items));
|
||||
}
|
||||
new_obj = PointerHolder<QPDFObject>(new QPDF_Dictionary(items));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("QPDFObjectHandle::makeDirectInternal: "
|
||||
"unknown object type");
|
||||
throw std::logic_error("QPDFObjectHandle::makeDirectInternal: "
|
||||
"unknown object type");
|
||||
}
|
||||
|
||||
this->obj = new_obj;
|
||||
|
||||
if (cur_og.getObj())
|
||||
{
|
||||
visited.erase(cur_og);
|
||||
visited.erase(cur_og);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3198,8 +3198,8 @@ QPDFObjectHandle::assertInitialized() const
|
||||
{
|
||||
if (! this->initialized)
|
||||
{
|
||||
throw std::logic_error("operation attempted on uninitialized "
|
||||
"QPDFObjectHandle");
|
||||
throw std::logic_error("operation attempted on uninitialized "
|
||||
"QPDFObjectHandle");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3257,7 +3257,7 @@ QPDFObjectHandle::assertType(char const* type_name, bool istype)
|
||||
{
|
||||
if (! istype)
|
||||
{
|
||||
throw std::runtime_error(std::string("operation for ") + type_name +
|
||||
throw std::runtime_error(std::string("operation for ") + type_name +
|
||||
" attempted on object of type " +
|
||||
getTypeName());
|
||||
}
|
||||
@ -3340,7 +3340,7 @@ QPDFObjectHandle::assertIndirect()
|
||||
{
|
||||
if (! isIndirect())
|
||||
{
|
||||
throw std::logic_error(
|
||||
throw std::logic_error(
|
||||
"operation for indirect object attempted on direct object");
|
||||
}
|
||||
}
|
||||
@ -3437,7 +3437,7 @@ QPDFObjectHandle::assertPageObject()
|
||||
{
|
||||
if (! isPageObject())
|
||||
{
|
||||
throw std::runtime_error("page operation called on non-Page object");
|
||||
throw std::runtime_error("page operation called on non-Page object");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3458,13 +3458,13 @@ QPDFObjectHandle::dereference()
|
||||
if (this->obj.get() == 0)
|
||||
{
|
||||
PointerHolder<QPDFObject> obj = QPDF::Resolver::resolve(
|
||||
this->qpdf, this->objid, this->generation);
|
||||
if (obj.get() == 0)
|
||||
{
|
||||
this->qpdf, this->objid, this->generation);
|
||||
if (obj.get() == 0)
|
||||
{
|
||||
// QPDF::resolve never returns an uninitialized object, but
|
||||
// check just in case.
|
||||
this->obj = PointerHolder<QPDFObject>(new QPDF_Null());
|
||||
}
|
||||
this->obj = PointerHolder<QPDFObject>(new QPDF_Null());
|
||||
}
|
||||
else if (dynamic_cast<QPDF_Reserved*>(obj.get()))
|
||||
{
|
||||
// Do not resolve
|
||||
|
@ -430,7 +430,7 @@ QPDFPageObjectHelper::forEachXObject(
|
||||
queue.push_back(QPDFPageObjectHelper(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,9 +240,9 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
{
|
||||
if (this->m->state == st_token_ready)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: QPDF tokenizer presented character "
|
||||
"while token is waiting");
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: QPDF tokenizer presented character "
|
||||
"while token is waiting");
|
||||
}
|
||||
|
||||
char orig_ch = ch;
|
||||
@ -254,87 +254,87 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
bool handled = true;
|
||||
if (this->m->state == st_top)
|
||||
{
|
||||
// Note: we specifically do not use ctype here. It is
|
||||
// locale-dependent.
|
||||
if (isSpace(ch))
|
||||
{
|
||||
// Note: we specifically do not use ctype here. It is
|
||||
// locale-dependent.
|
||||
if (isSpace(ch))
|
||||
{
|
||||
if (this->m->include_ignorable)
|
||||
{
|
||||
this->m->state = st_in_space;
|
||||
this->m->val += ch;
|
||||
}
|
||||
}
|
||||
else if (ch == '%')
|
||||
{
|
||||
this->m->state = st_in_comment;
|
||||
}
|
||||
else if (ch == '%')
|
||||
{
|
||||
this->m->state = st_in_comment;
|
||||
if (this->m->include_ignorable)
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
this->m->string_depth = 1;
|
||||
this->m->string_ignoring_newline = false;
|
||||
memset(this->m->bs_num_register, '\0',
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
this->m->string_depth = 1;
|
||||
this->m->string_ignoring_newline = false;
|
||||
memset(this->m->bs_num_register, '\0',
|
||||
sizeof(this->m->bs_num_register));
|
||||
this->m->last_char_was_bs = false;
|
||||
this->m->last_char_was_cr = false;
|
||||
this->m->state = st_in_string;
|
||||
}
|
||||
else if (ch == '<')
|
||||
{
|
||||
this->m->state = st_lt;
|
||||
}
|
||||
else if (ch == '>')
|
||||
{
|
||||
this->m->state = st_gt;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val += ch;
|
||||
if (ch == ')')
|
||||
{
|
||||
this->m->type = tt_bad;
|
||||
QTC::TC("qpdf", "QPDFTokenizer bad )");
|
||||
this->m->error_message = "unexpected )";
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '[')
|
||||
{
|
||||
this->m->type = tt_array_open;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == ']')
|
||||
{
|
||||
this->m->type = tt_array_close;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '{')
|
||||
{
|
||||
this->m->type = tt_brace_open;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '}')
|
||||
{
|
||||
this->m->type = tt_brace_close;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->state = st_literal;
|
||||
}
|
||||
}
|
||||
this->m->last_char_was_bs = false;
|
||||
this->m->last_char_was_cr = false;
|
||||
this->m->state = st_in_string;
|
||||
}
|
||||
else if (ch == '<')
|
||||
{
|
||||
this->m->state = st_lt;
|
||||
}
|
||||
else if (ch == '>')
|
||||
{
|
||||
this->m->state = st_gt;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val += ch;
|
||||
if (ch == ')')
|
||||
{
|
||||
this->m->type = tt_bad;
|
||||
QTC::TC("qpdf", "QPDFTokenizer bad )");
|
||||
this->m->error_message = "unexpected )";
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '[')
|
||||
{
|
||||
this->m->type = tt_array_open;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == ']')
|
||||
{
|
||||
this->m->type = tt_array_close;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '{')
|
||||
{
|
||||
this->m->type = tt_brace_open;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '}')
|
||||
{
|
||||
this->m->type = tt_brace_close;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->state = st_literal;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this->m->state == st_in_space)
|
||||
{
|
||||
// We only enter this state if include_ignorable is true.
|
||||
if (! isSpace(ch))
|
||||
{
|
||||
this->m->type = tt_space;
|
||||
this->m->unread_char = true;
|
||||
this->m->char_to_unread = ch;
|
||||
this->m->state = st_token_ready;
|
||||
this->m->type = tt_space;
|
||||
this->m->unread_char = true;
|
||||
this->m->char_to_unread = ch;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -343,7 +343,7 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
}
|
||||
else if (this->m->state == st_in_comment)
|
||||
{
|
||||
if ((ch == '\r') || (ch == '\n'))
|
||||
if ((ch == '\r') || (ch == '\n'))
|
||||
{
|
||||
if (this->m->include_ignorable)
|
||||
{
|
||||
@ -364,124 +364,124 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
}
|
||||
else if (this->m->state == st_lt)
|
||||
{
|
||||
if (ch == '<')
|
||||
{
|
||||
this->m->val = "<<";
|
||||
this->m->type = tt_dict_open;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
handled = false;
|
||||
this->m->state = st_in_hexstring;
|
||||
}
|
||||
if (ch == '<')
|
||||
{
|
||||
this->m->val = "<<";
|
||||
this->m->type = tt_dict_open;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
handled = false;
|
||||
this->m->state = st_in_hexstring;
|
||||
}
|
||||
}
|
||||
else if (this->m->state == st_gt)
|
||||
{
|
||||
if (ch == '>')
|
||||
{
|
||||
this->m->val = ">>";
|
||||
this->m->type = tt_dict_close;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val = ">";
|
||||
this->m->type = tt_bad;
|
||||
QTC::TC("qpdf", "QPDFTokenizer bad >");
|
||||
this->m->error_message = "unexpected >";
|
||||
this->m->unread_char = true;
|
||||
this->m->char_to_unread = ch;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
if (ch == '>')
|
||||
{
|
||||
this->m->val = ">>";
|
||||
this->m->type = tt_dict_close;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val = ">";
|
||||
this->m->type = tt_bad;
|
||||
QTC::TC("qpdf", "QPDFTokenizer bad >");
|
||||
this->m->error_message = "unexpected >";
|
||||
this->m->unread_char = true;
|
||||
this->m->char_to_unread = ch;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
}
|
||||
else if (this->m->state == st_in_string)
|
||||
{
|
||||
if (this->m->string_ignoring_newline && (ch != '\n'))
|
||||
{
|
||||
this->m->string_ignoring_newline = false;
|
||||
}
|
||||
|
||||
size_t bs_num_count = strlen(this->m->bs_num_register);
|
||||
bool ch_is_octal = ((ch >= '0') && (ch <= '7'));
|
||||
if ((bs_num_count == 3) || ((bs_num_count > 0) && (! ch_is_octal)))
|
||||
{
|
||||
// We've accumulated \ddd. PDF Spec says to ignore
|
||||
// high-order overflow.
|
||||
this->m->val += static_cast<char>(
|
||||
strtol(this->m->bs_num_register, 0, 8));
|
||||
memset(this->m->bs_num_register, '\0',
|
||||
sizeof(this->m->bs_num_register));
|
||||
bs_num_count = 0;
|
||||
}
|
||||
|
||||
if (this->m->string_ignoring_newline && (ch == '\n'))
|
||||
{
|
||||
// ignore
|
||||
if (this->m->string_ignoring_newline && (ch != '\n'))
|
||||
{
|
||||
this->m->string_ignoring_newline = false;
|
||||
}
|
||||
else if (ch_is_octal &&
|
||||
}
|
||||
|
||||
size_t bs_num_count = strlen(this->m->bs_num_register);
|
||||
bool ch_is_octal = ((ch >= '0') && (ch <= '7'));
|
||||
if ((bs_num_count == 3) || ((bs_num_count > 0) && (! ch_is_octal)))
|
||||
{
|
||||
// We've accumulated \ddd. PDF Spec says to ignore
|
||||
// high-order overflow.
|
||||
this->m->val += static_cast<char>(
|
||||
strtol(this->m->bs_num_register, 0, 8));
|
||||
memset(this->m->bs_num_register, '\0',
|
||||
sizeof(this->m->bs_num_register));
|
||||
bs_num_count = 0;
|
||||
}
|
||||
|
||||
if (this->m->string_ignoring_newline && (ch == '\n'))
|
||||
{
|
||||
// ignore
|
||||
this->m->string_ignoring_newline = false;
|
||||
}
|
||||
else if (ch_is_octal &&
|
||||
(this->m->last_char_was_bs || (bs_num_count > 0)))
|
||||
{
|
||||
this->m->bs_num_register[bs_num_count++] = ch;
|
||||
}
|
||||
else if (this->m->last_char_was_bs)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'n':
|
||||
this->m->val += '\n';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
this->m->val += '\r';
|
||||
break;
|
||||
|
||||
case 't':
|
||||
this->m->val += '\t';
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
this->m->val += '\b';
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
this->m->val += '\f';
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
{
|
||||
this->m->bs_num_register[bs_num_count++] = ch;
|
||||
}
|
||||
else if (this->m->last_char_was_bs)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 'n':
|
||||
this->m->val += '\n';
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
this->m->string_ignoring_newline = true;
|
||||
break;
|
||||
case 'r':
|
||||
this->m->val += '\r';
|
||||
break;
|
||||
|
||||
default:
|
||||
// PDF spec says backslash is ignored before anything else
|
||||
this->m->val += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ch == '\\')
|
||||
{
|
||||
// last_char_was_bs is set/cleared below as appropriate
|
||||
if (bs_num_count)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: QPDFTokenizer: bs_num_count != 0 "
|
||||
"when ch == '\\'");
|
||||
}
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
this->m->val += ch;
|
||||
++this->m->string_depth;
|
||||
}
|
||||
else if ((ch == ')') && (--this->m->string_depth == 0))
|
||||
{
|
||||
this->m->type = tt_string;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
case 't':
|
||||
this->m->val += '\t';
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
this->m->val += '\b';
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
this->m->val += '\f';
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
this->m->string_ignoring_newline = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// PDF spec says backslash is ignored before anything else
|
||||
this->m->val += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ch == '\\')
|
||||
{
|
||||
// last_char_was_bs is set/cleared below as appropriate
|
||||
if (bs_num_count)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: QPDFTokenizer: bs_num_count != 0 "
|
||||
"when ch == '\\'");
|
||||
}
|
||||
}
|
||||
else if (ch == '(')
|
||||
{
|
||||
this->m->val += ch;
|
||||
++this->m->string_depth;
|
||||
}
|
||||
else if ((ch == ')') && (--this->m->string_depth == 0))
|
||||
{
|
||||
this->m->type = tt_string;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else if (ch == '\r')
|
||||
{
|
||||
// CR by itself is converted to LF
|
||||
@ -495,37 +495,37 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
this->m->val += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
|
||||
this->m->last_char_was_cr =
|
||||
((! this->m->string_ignoring_newline) && (ch == '\r'));
|
||||
this->m->last_char_was_bs =
|
||||
this->m->last_char_was_bs =
|
||||
((! this->m->last_char_was_bs) && (ch == '\\'));
|
||||
}
|
||||
else if (this->m->state == st_literal)
|
||||
{
|
||||
if (isDelimiter(ch))
|
||||
{
|
||||
// A C-locale whitespace character or delimiter terminates
|
||||
// token. It is important to unread the whitespace
|
||||
// character even though it is ignored since it may be the
|
||||
// newline after a stream keyword. Removing it here could
|
||||
// make the stream-reading code break on some files,
|
||||
// though not on any files in the test suite as of this
|
||||
// writing.
|
||||
if (isDelimiter(ch))
|
||||
{
|
||||
// A C-locale whitespace character or delimiter terminates
|
||||
// token. It is important to unread the whitespace
|
||||
// character even though it is ignored since it may be the
|
||||
// newline after a stream keyword. Removing it here could
|
||||
// make the stream-reading code break on some files,
|
||||
// though not on any files in the test suite as of this
|
||||
// writing.
|
||||
|
||||
this->m->type = tt_word;
|
||||
this->m->unread_char = true;
|
||||
this->m->char_to_unread = ch;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
this->m->type = tt_word;
|
||||
this->m->unread_char = true;
|
||||
this->m->char_to_unread = ch;
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
}
|
||||
else if (this->m->state == st_inline_image)
|
||||
{
|
||||
@ -541,58 +541,58 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
}
|
||||
else
|
||||
{
|
||||
handled = false;
|
||||
handled = false;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
{
|
||||
// okay
|
||||
// okay
|
||||
}
|
||||
else if (this->m->state == st_in_hexstring)
|
||||
{
|
||||
if (ch == '>')
|
||||
{
|
||||
this->m->type = tt_string;
|
||||
this->m->state = st_token_ready;
|
||||
if (this->m->val.length() % 2)
|
||||
{
|
||||
// PDF spec says odd hexstrings have implicit
|
||||
// trailing 0.
|
||||
this->m->val += '0';
|
||||
}
|
||||
char num[3];
|
||||
num[2] = '\0';
|
||||
std::string nval;
|
||||
for (unsigned int i = 0; i < this->m->val.length(); i += 2)
|
||||
{
|
||||
num[0] = this->m->val.at(i);
|
||||
num[1] = this->m->val.at(i+1);
|
||||
char nch = static_cast<char>(strtol(num, 0, 16));
|
||||
nval += nch;
|
||||
}
|
||||
this->m->val = nval;
|
||||
}
|
||||
else if (QUtil::is_hex_digit(ch))
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
else if (isSpace(ch))
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->type = tt_bad;
|
||||
QTC::TC("qpdf", "QPDFTokenizer bad hexstring character");
|
||||
this->m->error_message = std::string("invalid character (") +
|
||||
ch + ") in hexstring";
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
if (ch == '>')
|
||||
{
|
||||
this->m->type = tt_string;
|
||||
this->m->state = st_token_ready;
|
||||
if (this->m->val.length() % 2)
|
||||
{
|
||||
// PDF spec says odd hexstrings have implicit
|
||||
// trailing 0.
|
||||
this->m->val += '0';
|
||||
}
|
||||
char num[3];
|
||||
num[2] = '\0';
|
||||
std::string nval;
|
||||
for (unsigned int i = 0; i < this->m->val.length(); i += 2)
|
||||
{
|
||||
num[0] = this->m->val.at(i);
|
||||
num[1] = this->m->val.at(i+1);
|
||||
char nch = static_cast<char>(strtol(num, 0, 16));
|
||||
nval += nch;
|
||||
}
|
||||
this->m->val = nval;
|
||||
}
|
||||
else if (QUtil::is_hex_digit(ch))
|
||||
{
|
||||
this->m->val += ch;
|
||||
}
|
||||
else if (isSpace(ch))
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->type = tt_bad;
|
||||
QTC::TC("qpdf", "QPDFTokenizer bad hexstring character");
|
||||
this->m->error_message = std::string("invalid character (") +
|
||||
ch + ") in hexstring";
|
||||
this->m->state = st_token_ready;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: invalid state while reading token");
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: invalid state while reading token");
|
||||
}
|
||||
|
||||
if ((this->m->state == st_token_ready) && (this->m->type == tt_word))
|
||||
@ -603,7 +603,7 @@ QPDFTokenizer::presentCharacter(char ch)
|
||||
if (! (betweenTokens() ||
|
||||
((this->m->state == st_token_ready) && this->m->unread_char)))
|
||||
{
|
||||
this->m->raw_val += orig_ch;
|
||||
this->m->raw_val += orig_ch;
|
||||
}
|
||||
}
|
||||
|
||||
@ -782,9 +782,9 @@ QPDFTokenizer::getToken(Token& token, bool& unread_char, char& ch)
|
||||
{
|
||||
this->m->val = this->m->raw_val;
|
||||
}
|
||||
token = Token(this->m->type, this->m->val,
|
||||
token = Token(this->m->type, this->m->val,
|
||||
this->m->raw_val, this->m->error_message);
|
||||
this->m->reset();
|
||||
this->m->reset();
|
||||
}
|
||||
return ready;
|
||||
}
|
||||
@ -811,9 +811,9 @@ QPDFTokenizer::readToken(PointerHolder<InputSource> input,
|
||||
bool presented_eof = false;
|
||||
while (! getToken(token, unread_char, char_to_unread))
|
||||
{
|
||||
char ch;
|
||||
if (input->read(&ch, 1) == 0)
|
||||
{
|
||||
char ch;
|
||||
if (input->read(&ch, 1) == 0)
|
||||
{
|
||||
if (! presented_eof)
|
||||
{
|
||||
presentEOF();
|
||||
@ -833,14 +833,14 @@ QPDFTokenizer::readToken(PointerHolder<InputSource> input,
|
||||
throw std::logic_error(
|
||||
"getToken returned false after presenting EOF");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
presentCharacter(ch);
|
||||
if (betweenTokens() && (input->getLastOffset() == offset))
|
||||
{
|
||||
++offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
presentCharacter(ch);
|
||||
if (betweenTokens() && (input->getLastOffset() == offset))
|
||||
{
|
||||
++offset;
|
||||
}
|
||||
if (max_len && (this->m->raw_val.length() >= max_len) &&
|
||||
(this->m->state != st_token_ready))
|
||||
{
|
||||
@ -851,12 +851,12 @@ QPDFTokenizer::readToken(PointerHolder<InputSource> input,
|
||||
this->m->error_message =
|
||||
"exceeded allowable length while reading token";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unread_char)
|
||||
{
|
||||
input->unreadCh(char_to_unread);
|
||||
input->unreadCh(char_to_unread);
|
||||
}
|
||||
|
||||
if (token.getType() != tt_eof)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,8 @@ QPDFXRefEntry::QPDFXRefEntry(int type, qpdf_offset_t field1, int field2) :
|
||||
{
|
||||
if ((type < 1) || (type > 2))
|
||||
{
|
||||
throw std::logic_error(
|
||||
"invalid xref type " + QUtil::int_to_string(type));
|
||||
throw std::logic_error(
|
||||
"invalid xref type " + QUtil::int_to_string(type));
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,8 +34,8 @@ QPDFXRefEntry::getOffset() const
|
||||
{
|
||||
if (this->type != 1)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"getOffset called for xref entry of type != 1");
|
||||
throw std::logic_error(
|
||||
"getOffset called for xref entry of type != 1");
|
||||
}
|
||||
return this->field1;
|
||||
}
|
||||
@ -45,8 +45,8 @@ QPDFXRefEntry::getObjStreamNumber() const
|
||||
{
|
||||
if (this->type != 2)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"getObjStreamNumber called for xref entry of type != 2");
|
||||
throw std::logic_error(
|
||||
"getObjStreamNumber called for xref entry of type != 2");
|
||||
}
|
||||
return QIntC::to_int(this->field1);
|
||||
}
|
||||
@ -56,8 +56,8 @@ QPDFXRefEntry::getObjStreamIndex() const
|
||||
{
|
||||
if (this->type != 2)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"getObjStreamIndex called for xref entry of type != 2");
|
||||
throw std::logic_error(
|
||||
"getObjStreamIndex called for xref entry of type != 2");
|
||||
}
|
||||
return this->field2;
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ QPDF_Array::unparse()
|
||||
size_t size = this->elements.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
result += this->elements.at(i).unparse();
|
||||
result += " ";
|
||||
result += this->elements.at(i).unparse();
|
||||
result += " ";
|
||||
}
|
||||
result += "]";
|
||||
return result;
|
||||
@ -81,8 +81,8 @@ QPDF_Array::getItem(int n) const
|
||||
{
|
||||
if ((n < 0) || (n >= QIntC::to_int(elements.size())))
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing QPDF_Array element");
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing QPDF_Array element");
|
||||
}
|
||||
return this->elements.at(QIntC::to_size(n));
|
||||
}
|
||||
@ -120,8 +120,8 @@ QPDF_Array::insertItem(int at, QPDFObjectHandle const& item)
|
||||
// As special case, also allow insert beyond the end
|
||||
if ((at < 0) || (at > QIntC::to_int(this->elements.size())))
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing QPDF_Array element");
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing QPDF_Array element");
|
||||
}
|
||||
this->elements.insert(QIntC::to_size(at), item);
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ void
|
||||
QPDF_Dictionary::releaseResolved()
|
||||
{
|
||||
for (std::map<std::string, QPDFObjectHandle>::iterator iter =
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
{
|
||||
QPDFObjectHandle::ReleaseResolver::releaseResolved((*iter).second);
|
||||
QPDFObjectHandle::ReleaseResolver::releaseResolved((*iter).second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,11 +29,11 @@ QPDF_Dictionary::unparse()
|
||||
{
|
||||
std::string result = "<< ";
|
||||
for (std::map<std::string, QPDFObjectHandle>::iterator iter =
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
{
|
||||
result += QPDF_Name::normalizeName((*iter).first) +
|
||||
" " + (*iter).second.unparse() + " ";
|
||||
result += QPDF_Name::normalizeName((*iter).first) +
|
||||
" " + (*iter).second.unparse() + " ";
|
||||
}
|
||||
result += ">>";
|
||||
return result;
|
||||
@ -44,8 +44,8 @@ QPDF_Dictionary::getJSON()
|
||||
{
|
||||
JSON j = JSON::makeDictionary();
|
||||
for (std::map<std::string, QPDFObjectHandle>::iterator iter =
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
{
|
||||
j.addDictionaryMember(QPDF_Name::normalizeName((*iter).first),
|
||||
(*iter).second.getJSON());
|
||||
@ -75,7 +75,7 @@ bool
|
||||
QPDF_Dictionary::hasKey(std::string const& key)
|
||||
{
|
||||
return ((this->items.count(key) > 0) &&
|
||||
(! this->items[key].isNull()));
|
||||
(! this->items[key].isNull()));
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
@ -85,8 +85,8 @@ QPDF_Dictionary::getKey(std::string const& key)
|
||||
// returns the null object.
|
||||
if (this->items.count(key))
|
||||
{
|
||||
// May be a null object
|
||||
return (*(this->items.find(key))).second;
|
||||
// May be a null object
|
||||
return (*(this->items.find(key))).second;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -98,7 +98,7 @@ QPDF_Dictionary::getKey(std::string const& key)
|
||||
null.setObjectDescription(
|
||||
qpdf, description + " -> dictionary key " + key);
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,13 +107,13 @@ QPDF_Dictionary::getKeys()
|
||||
{
|
||||
std::set<std::string> result;
|
||||
for (std::map<std::string, QPDFObjectHandle>::const_iterator iter =
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
this->items.begin();
|
||||
iter != this->items.end(); ++iter)
|
||||
{
|
||||
if (hasKey((*iter).first))
|
||||
{
|
||||
result.insert((*iter).first);
|
||||
}
|
||||
if (hasKey((*iter).first))
|
||||
{
|
||||
result.insert((*iter).first);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -126,7 +126,7 @@ QPDF_Dictionary::getAsMap() const
|
||||
|
||||
void
|
||||
QPDF_Dictionary::replaceKey(std::string const& key,
|
||||
QPDFObjectHandle value)
|
||||
QPDFObjectHandle value)
|
||||
{
|
||||
// add or replace value
|
||||
this->items[key] = value;
|
||||
@ -141,14 +141,14 @@ QPDF_Dictionary::removeKey(std::string const& key)
|
||||
|
||||
void
|
||||
QPDF_Dictionary::replaceOrRemoveKey(std::string const& key,
|
||||
QPDFObjectHandle value)
|
||||
QPDFObjectHandle value)
|
||||
{
|
||||
if (value.isNull())
|
||||
{
|
||||
removeKey(key);
|
||||
removeKey(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
replaceKey(key, value);
|
||||
replaceKey(key, value);
|
||||
}
|
||||
}
|
||||
|
@ -18,28 +18,28 @@ QPDF_Name::normalizeName(std::string const& name)
|
||||
{
|
||||
if (name.empty())
|
||||
{
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
std::string result;
|
||||
result += name.at(0);
|
||||
for (size_t i = 1; i < name.length(); ++i)
|
||||
{
|
||||
char ch = name.at(i);
|
||||
// Don't use locale/ctype here; follow PDF spec guidelines.
|
||||
char ch = name.at(i);
|
||||
// Don't use locale/ctype here; follow PDF spec guidelines.
|
||||
if (ch == '\0')
|
||||
{
|
||||
// QPDFTokenizer embeds a null character to encode an
|
||||
// invalid #.
|
||||
result += "#";
|
||||
}
|
||||
else if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126))
|
||||
{
|
||||
else if (strchr("#()<>[]{}/%", ch) || (ch < 33) || (ch > 126))
|
||||
{
|
||||
result += "#" + QUtil::hex_encode(std::string(&ch, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
result += ch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result += ch;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -83,8 +83,8 @@ QPDF_Stream::filter_factories = {
|
||||
};
|
||||
|
||||
QPDF_Stream::QPDF_Stream(QPDF* qpdf, int objid, int generation,
|
||||
QPDFObjectHandle stream_dict,
|
||||
qpdf_offset_t offset, size_t length) :
|
||||
QPDFObjectHandle stream_dict,
|
||||
qpdf_offset_t offset, size_t length) :
|
||||
qpdf(qpdf),
|
||||
objid(objid),
|
||||
generation(generation),
|
||||
@ -95,9 +95,9 @@ QPDF_Stream::QPDF_Stream(QPDF* qpdf, int objid, int generation,
|
||||
{
|
||||
if (! stream_dict.isDictionary())
|
||||
{
|
||||
throw std::logic_error(
|
||||
"stream object instantiated with non-dictionary "
|
||||
"object for dictionary");
|
||||
throw std::logic_error(
|
||||
"stream object instantiated with non-dictionary "
|
||||
"object for dictionary");
|
||||
}
|
||||
setStreamDescription();
|
||||
}
|
||||
@ -138,9 +138,9 @@ QPDF_Stream::setObjGen(int objid, int generation)
|
||||
{
|
||||
if (! ((this->objid == 0) && (this->generation == 0)))
|
||||
{
|
||||
throw std::logic_error(
|
||||
"attempt to set object ID and generation of a stream"
|
||||
" that already has them");
|
||||
throw std::logic_error(
|
||||
"attempt to set object ID and generation of a stream"
|
||||
" that already has them");
|
||||
}
|
||||
this->objid = objid;
|
||||
this->generation = generation;
|
||||
@ -151,7 +151,7 @@ QPDF_Stream::unparse()
|
||||
{
|
||||
// Unparse stream objects as indirect references
|
||||
return QUtil::int_to_string(this->objid) + " " +
|
||||
QUtil::int_to_string(this->generation) + " R";
|
||||
QUtil::int_to_string(this->generation) + " R";
|
||||
}
|
||||
|
||||
JSON
|
||||
@ -246,7 +246,7 @@ QPDF_Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
|
||||
pipeStreamData(&buf, &filtered, 0, decode_level, false, false);
|
||||
if (! filtered)
|
||||
{
|
||||
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
||||
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"getStreamData called on unfilterable stream");
|
||||
}
|
||||
@ -260,7 +260,7 @@ QPDF_Stream::getRawStreamData()
|
||||
Pl_Buffer buf("stream data buffer");
|
||||
if (! pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false))
|
||||
{
|
||||
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
||||
throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"error getting raw stream data");
|
||||
}
|
||||
@ -283,39 +283,39 @@ QPDF_Stream::filterable(
|
||||
|
||||
if (filter_obj.isNull())
|
||||
{
|
||||
// No filters
|
||||
// No filters
|
||||
}
|
||||
else if (filter_obj.isName())
|
||||
{
|
||||
// One filter
|
||||
filter_names.push_back(filter_obj.getName());
|
||||
// One filter
|
||||
filter_names.push_back(filter_obj.getName());
|
||||
}
|
||||
else if (filter_obj.isArray())
|
||||
{
|
||||
// Potentially multiple filters
|
||||
int n = filter_obj.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
QPDFObjectHandle item = filter_obj.getArrayItem(i);
|
||||
if (item.isName())
|
||||
{
|
||||
filter_names.push_back(item.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
filters_okay = false;
|
||||
}
|
||||
}
|
||||
// Potentially multiple filters
|
||||
int n = filter_obj.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
QPDFObjectHandle item = filter_obj.getArrayItem(i);
|
||||
if (item.isName())
|
||||
{
|
||||
filter_names.push_back(item.getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
filters_okay = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filters_okay = false;
|
||||
filters_okay = false;
|
||||
}
|
||||
|
||||
if (! filters_okay)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream invalid filter");
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
|
||||
QTC::TC("qpdf", "QPDF_Stream invalid filter");
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
|
||||
"", this->offset,
|
||||
"stream filter type is not name or array"));
|
||||
return false;
|
||||
@ -325,11 +325,11 @@ QPDF_Stream::filterable(
|
||||
|
||||
for (auto& filter_name: filter_names)
|
||||
{
|
||||
if (filter_abbreviations.count(filter_name))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream expand filter abbreviation");
|
||||
filter_name = filter_abbreviations[filter_name];
|
||||
}
|
||||
if (filter_abbreviations.count(filter_name))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream expand filter abbreviation");
|
||||
filter_name = filter_abbreviations[filter_name];
|
||||
}
|
||||
|
||||
auto ff = filter_factories.find(filter_name);
|
||||
if (ff == filter_factories.end())
|
||||
@ -435,7 +435,7 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
bool success = true;
|
||||
if (filter)
|
||||
{
|
||||
filter = filterable(
|
||||
filter = filterable(
|
||||
filters, specialized_compression, lossy_compression);
|
||||
if ((decode_level < qpdf_dl_all) && lossy_compression)
|
||||
{
|
||||
@ -454,9 +454,9 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
|
||||
if (pipeline == 0)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream pipeStreamData with null pipeline");
|
||||
QTC::TC("qpdf", "QPDF_Stream pipeStreamData with null pipeline");
|
||||
// Return value is whether we can filter in this case.
|
||||
return filter;
|
||||
return filter;
|
||||
}
|
||||
|
||||
// Construct the pipeline in reverse order. Force pipelines we
|
||||
@ -469,22 +469,22 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
std::shared_ptr<Pipeline> new_pipeline;
|
||||
if (filter)
|
||||
{
|
||||
if (encode_flags & qpdf_ef_compress)
|
||||
{
|
||||
new_pipeline = std::make_shared<Pl_Flate>(
|
||||
if (encode_flags & qpdf_ef_compress)
|
||||
{
|
||||
new_pipeline = std::make_shared<Pl_Flate>(
|
||||
"compress stream", pipeline, Pl_Flate::a_deflate);
|
||||
to_delete.push_back(new_pipeline);
|
||||
to_delete.push_back(new_pipeline);
|
||||
pipeline = new_pipeline.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (encode_flags & qpdf_ef_normalize)
|
||||
{
|
||||
if (encode_flags & qpdf_ef_normalize)
|
||||
{
|
||||
normalizer = make_pointer_holder<ContentNormalizer>();
|
||||
new_pipeline = std::make_shared<Pl_QPDFTokenizer>(
|
||||
new_pipeline = std::make_shared<Pl_QPDFTokenizer>(
|
||||
"normalizer", normalizer.get(), pipeline);
|
||||
to_delete.push_back(new_pipeline);
|
||||
to_delete.push_back(new_pipeline);
|
||||
pipeline = new_pipeline.get();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = this->token_filters.rbegin();
|
||||
iter != this->token_filters.rend(); ++iter)
|
||||
@ -495,9 +495,9 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
pipeline = new_pipeline.get();
|
||||
}
|
||||
|
||||
for (auto f_iter = filters.rbegin();
|
||||
for (auto f_iter = filters.rbegin();
|
||||
f_iter != filters.rend(); ++f_iter)
|
||||
{
|
||||
{
|
||||
auto decode_pipeline = (*f_iter)->getDecodePipeline(pipeline);
|
||||
if (decode_pipeline)
|
||||
{
|
||||
@ -511,19 +511,19 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
"", this->offset, msg));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->stream_data.get())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe replaced stream data");
|
||||
pipeline->write(this->stream_data->getBuffer(),
|
||||
this->stream_data->getSize());
|
||||
pipeline->finish();
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe replaced stream data");
|
||||
pipeline->write(this->stream_data->getBuffer(),
|
||||
this->stream_data->getSize());
|
||||
pipeline->finish();
|
||||
}
|
||||
else if (this->stream_provider.get())
|
||||
{
|
||||
Pl_Count count("stream provider count", pipeline);
|
||||
Pl_Count count("stream provider count", pipeline);
|
||||
if (this->stream_provider->supportsRetry())
|
||||
{
|
||||
if (! this->stream_provider->provideStreamData(
|
||||
@ -539,11 +539,11 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
this->stream_provider->provideStreamData(
|
||||
this->objid, this->generation, &count);
|
||||
}
|
||||
qpdf_offset_t actual_length = count.getCount();
|
||||
qpdf_offset_t desired_length = 0;
|
||||
qpdf_offset_t actual_length = count.getCount();
|
||||
qpdf_offset_t desired_length = 0;
|
||||
if (success && this->stream_dict.hasKey("/Length"))
|
||||
{
|
||||
desired_length = this->stream_dict.getKey("/Length").getIntValue();
|
||||
desired_length = this->stream_dict.getKey("/Length").getIntValue();
|
||||
if (actual_length == desired_length)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe use stream provider");
|
||||
@ -572,14 +572,14 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
}
|
||||
else if (this->offset == 0)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe no stream data");
|
||||
throw std::logic_error(
|
||||
"pipeStreamData called for stream with no data");
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe no stream data");
|
||||
throw std::logic_error(
|
||||
"pipeStreamData called for stream with no data");
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe original stream data");
|
||||
if (! QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
|
||||
QTC::TC("qpdf", "QPDF_Stream pipe original stream data");
|
||||
if (! QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
|
||||
this->offset, this->length,
|
||||
this->stream_dict, pipeline,
|
||||
suppress_warnings,
|
||||
@ -622,8 +622,8 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool* filterp,
|
||||
|
||||
void
|
||||
QPDF_Stream::replaceStreamData(PointerHolder<Buffer> data,
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms)
|
||||
{
|
||||
this->stream_data = data;
|
||||
this->stream_provider = 0;
|
||||
@ -650,8 +650,8 @@ QPDF_Stream::addTokenFilter(
|
||||
|
||||
void
|
||||
QPDF_Stream::replaceFilterData(QPDFObjectHandle const& filter,
|
||||
QPDFObjectHandle const& decode_parms,
|
||||
size_t length)
|
||||
QPDFObjectHandle const& decode_parms,
|
||||
size_t length)
|
||||
{
|
||||
this->stream_dict.replaceOrRemoveKey("/Filter", filter);
|
||||
this->stream_dict.replaceOrRemoveKey("/DecodeParms", decode_parms);
|
||||
|
@ -70,102 +70,102 @@ QPDF_String::unparse(bool force_binary)
|
||||
bool use_hexstring = force_binary;
|
||||
if (! use_hexstring)
|
||||
{
|
||||
unsigned int nonprintable = 0;
|
||||
int consecutive_printable = 0;
|
||||
for (unsigned int i = 0; i < this->val.length(); ++i)
|
||||
{
|
||||
char ch = this->val.at(i);
|
||||
// Note: do not use locale to determine printability. The
|
||||
// PDF specification accepts arbitrary binary data. Some
|
||||
// locales imply multibyte characters. We'll consider
|
||||
// something printable if it is printable in 7-bit ASCII.
|
||||
// We'll code this manually rather than being rude and
|
||||
// setting locale.
|
||||
if ((ch == 0) || (! (is_ascii_printable(ch) ||
|
||||
strchr("\n\r\t\b\f", ch))))
|
||||
{
|
||||
++nonprintable;
|
||||
consecutive_printable = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++consecutive_printable > 5)
|
||||
{
|
||||
// If there are more than 5 consecutive printable
|
||||
// characters, I want to see them as such.
|
||||
nonprintable = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int nonprintable = 0;
|
||||
int consecutive_printable = 0;
|
||||
for (unsigned int i = 0; i < this->val.length(); ++i)
|
||||
{
|
||||
char ch = this->val.at(i);
|
||||
// Note: do not use locale to determine printability. The
|
||||
// PDF specification accepts arbitrary binary data. Some
|
||||
// locales imply multibyte characters. We'll consider
|
||||
// something printable if it is printable in 7-bit ASCII.
|
||||
// We'll code this manually rather than being rude and
|
||||
// setting locale.
|
||||
if ((ch == 0) || (! (is_ascii_printable(ch) ||
|
||||
strchr("\n\r\t\b\f", ch))))
|
||||
{
|
||||
++nonprintable;
|
||||
consecutive_printable = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++consecutive_printable > 5)
|
||||
{
|
||||
// If there are more than 5 consecutive printable
|
||||
// characters, I want to see them as such.
|
||||
nonprintable = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use hex notation if more than 20% of the characters are not
|
||||
// printable in plain ASCII.
|
||||
if (5 * nonprintable > val.length())
|
||||
{
|
||||
use_hexstring = true;
|
||||
}
|
||||
// Use hex notation if more than 20% of the characters are not
|
||||
// printable in plain ASCII.
|
||||
if (5 * nonprintable > val.length())
|
||||
{
|
||||
use_hexstring = true;
|
||||
}
|
||||
}
|
||||
std::string result;
|
||||
if (use_hexstring)
|
||||
{
|
||||
result += "<" + QUtil::hex_encode(this->val) + ">";
|
||||
result += "<" + QUtil::hex_encode(this->val) + ">";
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "(";
|
||||
for (unsigned int i = 0; i < this->val.length(); ++i)
|
||||
{
|
||||
char ch = this->val.at(i);
|
||||
switch (ch)
|
||||
{
|
||||
case '\n':
|
||||
result += "\\n";
|
||||
break;
|
||||
result += "(";
|
||||
for (unsigned int i = 0; i < this->val.length(); ++i)
|
||||
{
|
||||
char ch = this->val.at(i);
|
||||
switch (ch)
|
||||
{
|
||||
case '\n':
|
||||
result += "\\n";
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
result += "\\r";
|
||||
break;
|
||||
case '\r':
|
||||
result += "\\r";
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
result += "\\t";
|
||||
break;
|
||||
case '\t':
|
||||
result += "\\t";
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
result += "\\b";
|
||||
break;
|
||||
case '\b':
|
||||
result += "\\b";
|
||||
break;
|
||||
|
||||
case '\f':
|
||||
result += "\\f";
|
||||
break;
|
||||
case '\f':
|
||||
result += "\\f";
|
||||
break;
|
||||
|
||||
case '(':
|
||||
result += "\\(";
|
||||
break;
|
||||
case '(':
|
||||
result += "\\(";
|
||||
break;
|
||||
|
||||
case ')':
|
||||
result += "\\)";
|
||||
break;
|
||||
case ')':
|
||||
result += "\\)";
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
result += "\\\\";
|
||||
break;
|
||||
case '\\':
|
||||
result += "\\\\";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (is_iso_latin1_printable(ch))
|
||||
{
|
||||
result += this->val.at(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\\" + QUtil::int_to_string_base(
|
||||
default:
|
||||
if (is_iso_latin1_printable(ch))
|
||||
{
|
||||
result += this->val.at(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += "\\" + QUtil::int_to_string_base(
|
||||
static_cast<int>(static_cast<unsigned char>(ch)),
|
||||
8, 3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
result += ")";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
result += ")";
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -147,7 +147,7 @@ QPDF::trim_user_password(std::string& user_password)
|
||||
size_t len = user_password.length();
|
||||
if (len < key_bytes)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
char const* p1 = cstr;
|
||||
@ -155,11 +155,11 @@ QPDF::trim_user_password(std::string& user_password)
|
||||
while ((p2 = strchr(p1, '\x28')) != 0)
|
||||
{
|
||||
size_t idx = toS(p2 - cstr);
|
||||
if (memcmp(p2, padding_string, len - idx) == 0)
|
||||
{
|
||||
user_password = user_password.substr(0, idx);
|
||||
return;
|
||||
}
|
||||
if (memcmp(p2, padding_string, len - idx) == 0)
|
||||
{
|
||||
user_password = user_password.substr(0, idx);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption skip 0x28");
|
||||
@ -191,30 +191,30 @@ iterate_md5_digest(MD5& md5, MD5::Digest& digest,
|
||||
|
||||
for (int i = 0; i < iterations; ++i)
|
||||
{
|
||||
MD5 m;
|
||||
m.encodeDataIncrementally(reinterpret_cast<char*>(digest),
|
||||
MD5 m;
|
||||
m.encodeDataIncrementally(reinterpret_cast<char*>(digest),
|
||||
QIntC::to_size(key_len));
|
||||
m.digest(digest);
|
||||
m.digest(digest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
iterate_rc4(unsigned char* data, size_t data_len,
|
||||
unsigned char* okey, int key_len,
|
||||
int iterations, bool reverse)
|
||||
unsigned char* okey, int key_len,
|
||||
int iterations, bool reverse)
|
||||
{
|
||||
auto key_ph = std::make_unique<unsigned char[]>(QIntC::to_size(key_len));
|
||||
unsigned char* key = key_ph.get();
|
||||
for (int i = 0; i < iterations; ++i)
|
||||
{
|
||||
int const xor_value = (reverse ? iterations - 1 - i : i);
|
||||
for (int j = 0; j < key_len; ++j)
|
||||
{
|
||||
key[j] = static_cast<unsigned char>(okey[j] ^ xor_value);
|
||||
}
|
||||
RC4 rc4(key, QIntC::to_int(key_len));
|
||||
rc4.process(data, data_len);
|
||||
int const xor_value = (reverse ? iterations - 1 - i : i);
|
||||
for (int j = 0; j < key_len; ++j)
|
||||
{
|
||||
key[j] = static_cast<unsigned char>(okey[j] ^ xor_value);
|
||||
}
|
||||
RC4 rc4(key, QIntC::to_int(key_len));
|
||||
rc4.process(data, data_len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,7 +354,7 @@ void pad_short_parameter(std::string& param, size_t max_len)
|
||||
|
||||
std::string
|
||||
QPDF::compute_data_key(std::string const& encryption_key,
|
||||
int objid, int generation, bool use_aes,
|
||||
int objid, int generation, bool use_aes,
|
||||
int encryption_V, int encryption_R)
|
||||
{
|
||||
// Algorithm 3.1 from the PDF 1.7 Reference Manual
|
||||
@ -376,7 +376,7 @@ QPDF::compute_data_key(std::string const& encryption_key,
|
||||
result.append(1, static_cast<char>((generation >> 8) & 0xff));
|
||||
if (use_aes)
|
||||
{
|
||||
result += "sAlT";
|
||||
result += "sAlT";
|
||||
}
|
||||
|
||||
MD5 md5;
|
||||
@ -384,7 +384,7 @@ QPDF::compute_data_key(std::string const& encryption_key,
|
||||
MD5::Digest digest;
|
||||
md5.digest(digest);
|
||||
return std::string(reinterpret_cast<char*>(digest),
|
||||
std::min(result.length(), toS(16)));
|
||||
std::min(result.length(), toS(16)));
|
||||
}
|
||||
|
||||
std::string
|
||||
@ -421,7 +421,7 @@ QPDF::compute_encryption_key_from_password(
|
||||
|
||||
MD5 md5;
|
||||
md5.encodeDataIncrementally(
|
||||
pad_or_truncate_password_V4(password).c_str(), key_bytes);
|
||||
pad_or_truncate_password_V4(password).c_str(), key_bytes);
|
||||
md5.encodeDataIncrementally(data.getO().c_str(), key_bytes);
|
||||
char pbytes[4];
|
||||
int P = data.getP();
|
||||
@ -434,9 +434,9 @@ QPDF::compute_encryption_key_from_password(
|
||||
data.getId1().length());
|
||||
if ((data.getR() >= 4) && (! data.getEncryptMetadata()))
|
||||
{
|
||||
char bytes[4];
|
||||
memset(bytes, 0xff, 4);
|
||||
md5.encodeDataIncrementally(bytes, 4);
|
||||
char bytes[4];
|
||||
memset(bytes, 0xff, 4);
|
||||
md5.encodeDataIncrementally(bytes, 4);
|
||||
}
|
||||
MD5::Digest digest;
|
||||
int key_len =
|
||||
@ -448,23 +448,23 @@ QPDF::compute_encryption_key_from_password(
|
||||
|
||||
static void
|
||||
compute_O_rc4_key(std::string const& user_password,
|
||||
std::string const& owner_password,
|
||||
QPDF::EncryptionData const& data,
|
||||
unsigned char key[OU_key_bytes_V4])
|
||||
std::string const& owner_password,
|
||||
QPDF::EncryptionData const& data,
|
||||
unsigned char key[OU_key_bytes_V4])
|
||||
{
|
||||
if (data.getV() >= 5)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"compute_O_rc4_key called for file with V >= 5");
|
||||
throw std::logic_error(
|
||||
"compute_O_rc4_key called for file with V >= 5");
|
||||
}
|
||||
std::string password = owner_password;
|
||||
if (password.empty())
|
||||
{
|
||||
password = user_password;
|
||||
password = user_password;
|
||||
}
|
||||
MD5 md5;
|
||||
md5.encodeDataIncrementally(
|
||||
pad_or_truncate_password_V4(password).c_str(), key_bytes);
|
||||
pad_or_truncate_password_V4(password).c_str(), key_bytes);
|
||||
MD5::Digest digest;
|
||||
int key_len = std::min(QIntC::to_int(sizeof(digest)),
|
||||
data.getLengthBytes());
|
||||
@ -474,8 +474,8 @@ compute_O_rc4_key(std::string const& user_password,
|
||||
|
||||
static std::string
|
||||
compute_O_value(std::string const& user_password,
|
||||
std::string const& owner_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
std::string const& owner_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
{
|
||||
// Algorithm 3.3 from the PDF 1.7 Reference Manual
|
||||
|
||||
@ -487,7 +487,7 @@ compute_O_value(std::string const& user_password,
|
||||
std::string k1(reinterpret_cast<char*>(O_key), OU_key_bytes_V4);
|
||||
pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
|
||||
iterate_rc4(QUtil::unsigned_char_pointer(upass), key_bytes,
|
||||
O_key, data.getLengthBytes(),
|
||||
O_key, data.getLengthBytes(),
|
||||
(data.getR() >= 3) ? 20 : 1, false);
|
||||
return std::string(upass, key_bytes);
|
||||
}
|
||||
@ -495,7 +495,7 @@ compute_O_value(std::string const& user_password,
|
||||
static
|
||||
std::string
|
||||
compute_U_value_R2(std::string const& user_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
QPDF::EncryptionData const& data)
|
||||
{
|
||||
// Algorithm 3.4 from the PDF 1.7 Reference Manual
|
||||
|
||||
@ -504,7 +504,7 @@ compute_U_value_R2(std::string const& user_password,
|
||||
pad_or_truncate_password_V4("", udata);
|
||||
pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
|
||||
iterate_rc4(QUtil::unsigned_char_pointer(udata), key_bytes,
|
||||
QUtil::unsigned_char_pointer(k1),
|
||||
QUtil::unsigned_char_pointer(k1),
|
||||
data.getLengthBytes(), 1, false);
|
||||
return std::string(udata, key_bytes);
|
||||
}
|
||||
@ -512,21 +512,21 @@ compute_U_value_R2(std::string const& user_password,
|
||||
static
|
||||
std::string
|
||||
compute_U_value_R3(std::string const& user_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
QPDF::EncryptionData const& data)
|
||||
{
|
||||
// Algorithm 3.5 from the PDF 1.7 Reference Manual
|
||||
|
||||
std::string k1 = QPDF::compute_encryption_key(user_password, data);
|
||||
MD5 md5;
|
||||
md5.encodeDataIncrementally(
|
||||
pad_or_truncate_password_V4("").c_str(), key_bytes);
|
||||
pad_or_truncate_password_V4("").c_str(), key_bytes);
|
||||
md5.encodeDataIncrementally(data.getId1().c_str(),
|
||||
data.getId1().length());
|
||||
MD5::Digest digest;
|
||||
md5.digest(digest);
|
||||
pad_short_parameter(k1, QIntC::to_size(data.getLengthBytes()));
|
||||
iterate_rc4(digest, sizeof(MD5::Digest),
|
||||
QUtil::unsigned_char_pointer(k1),
|
||||
QUtil::unsigned_char_pointer(k1),
|
||||
data.getLengthBytes(), 20, false);
|
||||
char result[key_bytes];
|
||||
memcpy(result, digest, sizeof(MD5::Digest));
|
||||
@ -534,18 +534,18 @@ compute_U_value_R3(std::string const& user_password,
|
||||
// testing
|
||||
for (unsigned int i = sizeof(MD5::Digest); i < key_bytes; ++i)
|
||||
{
|
||||
result[i] = static_cast<char>((i * i) % 0xff);
|
||||
result[i] = static_cast<char>((i * i) % 0xff);
|
||||
}
|
||||
return std::string(result, key_bytes);
|
||||
}
|
||||
|
||||
static std::string
|
||||
compute_U_value(std::string const& user_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
QPDF::EncryptionData const& data)
|
||||
{
|
||||
if (data.getR() >= 3)
|
||||
{
|
||||
return compute_U_value_R3(user_password, data);
|
||||
return compute_U_value_R3(user_password, data);
|
||||
}
|
||||
|
||||
return compute_U_value_R2(user_password, data);
|
||||
@ -577,7 +577,7 @@ check_user_password_V5(std::string const& user_password,
|
||||
|
||||
static bool
|
||||
check_user_password(std::string const& user_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
QPDF::EncryptionData const& data)
|
||||
{
|
||||
if (data.getV() < 5)
|
||||
{
|
||||
@ -632,8 +632,8 @@ check_owner_password_V5(std::string const& owner_password,
|
||||
|
||||
static bool
|
||||
check_owner_password(std::string& user_password,
|
||||
std::string const& owner_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
std::string const& owner_password,
|
||||
QPDF::EncryptionData const& data)
|
||||
{
|
||||
if (data.getV() < 5)
|
||||
{
|
||||
@ -773,24 +773,24 @@ QPDF::interpretCF(
|
||||
{
|
||||
if (cf.isName())
|
||||
{
|
||||
std::string filter = cf.getName();
|
||||
if (encp->crypt_filters.count(filter) != 0)
|
||||
{
|
||||
return encp->crypt_filters[filter];
|
||||
}
|
||||
else if (filter == "/Identity")
|
||||
{
|
||||
return e_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
return e_unknown;
|
||||
}
|
||||
std::string filter = cf.getName();
|
||||
if (encp->crypt_filters.count(filter) != 0)
|
||||
{
|
||||
return encp->crypt_filters[filter];
|
||||
}
|
||||
else if (filter == "/Identity")
|
||||
{
|
||||
return e_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
return e_unknown;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default: /Identity
|
||||
return e_none;
|
||||
// Default: /Identity
|
||||
return e_none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,7 +799,7 @@ QPDF::initializeEncryption()
|
||||
{
|
||||
if (this->m->encp->encryption_initialized)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
this->m->encp->encryption_initialized = true;
|
||||
|
||||
@ -810,7 +810,7 @@ QPDF::initializeEncryption()
|
||||
|
||||
if (! this->m->trailer.hasKey("/Encrypt"))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// Go ahead and set this->m->encrypted here. That way, isEncrypted
|
||||
@ -831,7 +831,7 @@ QPDF::initializeEncryption()
|
||||
// Treating a missing ID as the empty string enables qpdf to
|
||||
// decrypt some invalid encrypted files with no /ID that
|
||||
// poppler can read but Adobe Reader can't.
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
"trailer", this->m->file->getLastOffset(),
|
||||
"invalid /ID in trailer dictionary"));
|
||||
}
|
||||
@ -839,37 +839,37 @@ QPDF::initializeEncryption()
|
||||
QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt");
|
||||
if (! encryption_dict.isDictionary())
|
||||
{
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"/Encrypt in trailer dictionary is not a dictionary");
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"/Encrypt in trailer dictionary is not a dictionary");
|
||||
}
|
||||
|
||||
if (! (encryption_dict.getKey("/Filter").isName() &&
|
||||
(encryption_dict.getKey("/Filter").getName() == "/Standard")))
|
||||
(encryption_dict.getKey("/Filter").getName() == "/Standard")))
|
||||
{
|
||||
throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"unsupported encryption filter");
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"unsupported encryption filter");
|
||||
}
|
||||
if (! encryption_dict.getKey("/SubFilter").isNull())
|
||||
{
|
||||
warn(QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"file uses encryption SubFilters,"
|
||||
" which qpdf does not support"));
|
||||
warn(QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"file uses encryption SubFilters,"
|
||||
" which qpdf does not support"));
|
||||
}
|
||||
|
||||
if (! (encryption_dict.getKey("/V").isInteger() &&
|
||||
encryption_dict.getKey("/R").isInteger() &&
|
||||
encryption_dict.getKey("/O").isString() &&
|
||||
encryption_dict.getKey("/U").isString() &&
|
||||
encryption_dict.getKey("/P").isInteger()))
|
||||
encryption_dict.getKey("/R").isInteger() &&
|
||||
encryption_dict.getKey("/O").isString() &&
|
||||
encryption_dict.getKey("/U").isString() &&
|
||||
encryption_dict.getKey("/P").isInteger()))
|
||||
{
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"some encryption dictionary parameters are missing "
|
||||
"or the wrong type");
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"some encryption dictionary parameters are missing "
|
||||
"or the wrong type");
|
||||
}
|
||||
|
||||
int V = encryption_dict.getKey("/V").getIntValueAsInt();
|
||||
@ -881,11 +881,11 @@ QPDF::initializeEncryption()
|
||||
// If supporting new encryption R/V values, remember to update
|
||||
// error message inside this if statement.
|
||||
if (! (((R >= 2) && (R <= 6)) &&
|
||||
((V == 1) || (V == 2) || (V == 4) || (V == 5))))
|
||||
((V == 1) || (V == 2) || (V == 4) || (V == 5))))
|
||||
{
|
||||
throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"Unsupported /R or /V in encryption dictionary; R = " +
|
||||
throw QPDFExc(qpdf_e_unsupported, this->m->file->getName(),
|
||||
"encryption dictionary", this->m->file->getLastOffset(),
|
||||
"Unsupported /R or /V in encryption dictionary; R = " +
|
||||
QUtil::int_to_string(R) + " (max 6), V = " +
|
||||
QUtil::int_to_string(V) + " (max 5)");
|
||||
}
|
||||
@ -969,58 +969,58 @@ QPDF::initializeEncryption()
|
||||
this->m->encp->encrypt_metadata = true;
|
||||
if ((V >= 4) && (encryption_dict.getKey("/EncryptMetadata").isBool()))
|
||||
{
|
||||
this->m->encp->encrypt_metadata =
|
||||
encryption_dict.getKey("/EncryptMetadata").getBoolValue();
|
||||
this->m->encp->encrypt_metadata =
|
||||
encryption_dict.getKey("/EncryptMetadata").getBoolValue();
|
||||
}
|
||||
|
||||
if ((V == 4) || (V == 5))
|
||||
{
|
||||
QPDFObjectHandle CF = encryption_dict.getKey("/CF");
|
||||
std::set<std::string> keys = CF.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& filter = *iter;
|
||||
QPDFObjectHandle cdict = CF.getKey(filter);
|
||||
if (cdict.isDictionary())
|
||||
{
|
||||
encryption_method_e method = e_none;
|
||||
if (cdict.getKey("/CFM").isName())
|
||||
{
|
||||
std::string method_name = cdict.getKey("/CFM").getName();
|
||||
if (method_name == "/V2")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption CFM V2");
|
||||
method = e_rc4;
|
||||
}
|
||||
else if (method_name == "/AESV2")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption CFM AESV2");
|
||||
method = e_aes;
|
||||
}
|
||||
else if (method_name == "/AESV3")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption CFM AESV3");
|
||||
method = e_aesv3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't complain now -- maybe we won't need
|
||||
// to reference this type.
|
||||
method = e_unknown;
|
||||
}
|
||||
}
|
||||
this->m->encp->crypt_filters[filter] = method;
|
||||
}
|
||||
}
|
||||
QPDFObjectHandle CF = encryption_dict.getKey("/CF");
|
||||
std::set<std::string> keys = CF.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& filter = *iter;
|
||||
QPDFObjectHandle cdict = CF.getKey(filter);
|
||||
if (cdict.isDictionary())
|
||||
{
|
||||
encryption_method_e method = e_none;
|
||||
if (cdict.getKey("/CFM").isName())
|
||||
{
|
||||
std::string method_name = cdict.getKey("/CFM").getName();
|
||||
if (method_name == "/V2")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption CFM V2");
|
||||
method = e_rc4;
|
||||
}
|
||||
else if (method_name == "/AESV2")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption CFM AESV2");
|
||||
method = e_aes;
|
||||
}
|
||||
else if (method_name == "/AESV3")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption CFM AESV3");
|
||||
method = e_aesv3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't complain now -- maybe we won't need
|
||||
// to reference this type.
|
||||
method = e_unknown;
|
||||
}
|
||||
}
|
||||
this->m->encp->crypt_filters[filter] = method;
|
||||
}
|
||||
}
|
||||
|
||||
QPDFObjectHandle StmF = encryption_dict.getKey("/StmF");
|
||||
QPDFObjectHandle StrF = encryption_dict.getKey("/StrF");
|
||||
QPDFObjectHandle EFF = encryption_dict.getKey("/EFF");
|
||||
this->m->encp->cf_stream = interpretCF(this->m->encp, StmF);
|
||||
this->m->encp->cf_string = interpretCF(this->m->encp, StrF);
|
||||
if (EFF.isName())
|
||||
{
|
||||
QPDFObjectHandle StmF = encryption_dict.getKey("/StmF");
|
||||
QPDFObjectHandle StrF = encryption_dict.getKey("/StrF");
|
||||
QPDFObjectHandle EFF = encryption_dict.getKey("/EFF");
|
||||
this->m->encp->cf_stream = interpretCF(this->m->encp, StmF);
|
||||
this->m->encp->cf_string = interpretCF(this->m->encp, StrF);
|
||||
if (EFF.isName())
|
||||
{
|
||||
// qpdf does not use this for anything other than
|
||||
// informational purposes. This is intended to instruct
|
||||
// conforming writers on which crypt filter should be used
|
||||
@ -1035,12 +1035,12 @@ QPDF::initializeEncryption()
|
||||
// at a file generated by something else, such as Acrobat
|
||||
// when specifying that only attachments should be
|
||||
// encrypted.
|
||||
this->m->encp->cf_file = interpretCF(this->m->encp, EFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->encp->cf_file = this->m->encp->cf_stream;
|
||||
}
|
||||
this->m->encp->cf_file = interpretCF(this->m->encp, EFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m->encp->cf_file = this->m->encp->cf_stream;
|
||||
}
|
||||
}
|
||||
|
||||
EncryptionData data(V, R, Length / 8,
|
||||
@ -1128,19 +1128,19 @@ QPDF::getKeyForObject(
|
||||
{
|
||||
if (! encp->encrypted)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"request for encryption key in non-encrypted PDF");
|
||||
throw std::logic_error(
|
||||
"request for encryption key in non-encrypted PDF");
|
||||
}
|
||||
|
||||
if (! ((objid == encp->cached_key_objid) &&
|
||||
(generation == encp->cached_key_generation)))
|
||||
(generation == encp->cached_key_generation)))
|
||||
{
|
||||
encp->cached_object_encryption_key =
|
||||
compute_data_key(encp->encryption_key, objid, generation,
|
||||
encp->cached_object_encryption_key =
|
||||
compute_data_key(encp->encryption_key, objid, generation,
|
||||
use_aes, encp->encryption_V,
|
||||
encp->encryption_R);
|
||||
encp->cached_key_objid = objid;
|
||||
encp->cached_key_generation = generation;
|
||||
encp->cached_key_objid = objid;
|
||||
encp->cached_key_generation = generation;
|
||||
}
|
||||
|
||||
return encp->cached_object_encryption_key;
|
||||
@ -1151,83 +1151,83 @@ QPDF::decryptString(std::string& str, int objid, int generation)
|
||||
{
|
||||
if (objid == 0)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
bool use_aes = false;
|
||||
if (this->m->encp->encryption_V >= 4)
|
||||
{
|
||||
switch (this->m->encp->cf_string)
|
||||
{
|
||||
case e_none:
|
||||
return;
|
||||
switch (this->m->encp->cf_string)
|
||||
{
|
||||
case e_none:
|
||||
return;
|
||||
|
||||
case e_aes:
|
||||
use_aes = true;
|
||||
break;
|
||||
|
||||
case e_aesv3:
|
||||
use_aes = true;
|
||||
break;
|
||||
|
||||
case e_rc4:
|
||||
break;
|
||||
|
||||
default:
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"unknown encryption filter for strings"
|
||||
" (check /StrF in /Encrypt dictionary);"
|
||||
" strings may be decrypted improperly"));
|
||||
// To avoid repeated warnings, reset cf_string. Assume
|
||||
// we'd want to use AES if V == 4.
|
||||
this->m->encp->cf_string = e_aes;
|
||||
case e_aes:
|
||||
use_aes = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case e_aesv3:
|
||||
use_aes = true;
|
||||
break;
|
||||
|
||||
case e_rc4:
|
||||
break;
|
||||
|
||||
default:
|
||||
warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"unknown encryption filter for strings"
|
||||
" (check /StrF in /Encrypt dictionary);"
|
||||
" strings may be decrypted improperly"));
|
||||
// To avoid repeated warnings, reset cf_string. Assume
|
||||
// we'd want to use AES if V == 4.
|
||||
this->m->encp->cf_string = e_aes;
|
||||
use_aes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string key = getKeyForObject(
|
||||
this->m->encp, objid, generation, use_aes);
|
||||
try
|
||||
{
|
||||
if (use_aes)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption aes decode string");
|
||||
Pl_Buffer bufpl("decrypted string");
|
||||
Pl_AES_PDF pl("aes decrypt string", &bufpl, false,
|
||||
QUtil::unsigned_char_pointer(key),
|
||||
if (use_aes)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption aes decode string");
|
||||
Pl_Buffer bufpl("decrypted string");
|
||||
Pl_AES_PDF pl("aes decrypt string", &bufpl, false,
|
||||
QUtil::unsigned_char_pointer(key),
|
||||
key.length());
|
||||
pl.write(QUtil::unsigned_char_pointer(str), str.length());
|
||||
pl.finish();
|
||||
auto buf = bufpl.getBufferSharedPointer();
|
||||
str = std::string(reinterpret_cast<char*>(buf->getBuffer()),
|
||||
pl.write(QUtil::unsigned_char_pointer(str), str.length());
|
||||
pl.finish();
|
||||
auto buf = bufpl.getBufferSharedPointer();
|
||||
str = std::string(reinterpret_cast<char*>(buf->getBuffer()),
|
||||
buf->getSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption rc4 decode string");
|
||||
size_t vlen = str.length();
|
||||
// Using PointerHolder guarantees that tmp will
|
||||
// be freed even if rc4.process throws an exception.
|
||||
auto tmp = QUtil::make_unique_cstr(str);
|
||||
RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length()));
|
||||
rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen);
|
||||
str = std::string(tmp.get(), vlen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption rc4 decode string");
|
||||
size_t vlen = str.length();
|
||||
// Using PointerHolder guarantees that tmp will
|
||||
// be freed even if rc4.process throws an exception.
|
||||
auto tmp = QUtil::make_unique_cstr(str);
|
||||
RC4 rc4(QUtil::unsigned_char_pointer(key), toI(key.length()));
|
||||
rc4.process(QUtil::unsigned_char_pointer(tmp.get()), vlen);
|
||||
str = std::string(tmp.get(), vlen);
|
||||
}
|
||||
}
|
||||
catch (QPDFExc&)
|
||||
{
|
||||
throw;
|
||||
throw;
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"error decrypting string for object " +
|
||||
QUtil::int_to_string(objid) + " " +
|
||||
QUtil::int_to_string(generation) + ": " + e.what());
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"error decrypting string for object " +
|
||||
QUtil::int_to_string(objid) + " " +
|
||||
QUtil::int_to_string(generation) + ": " + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1236,26 +1236,26 @@ QPDF::decryptStream(PointerHolder<EncryptionParameters> encp,
|
||||
PointerHolder<InputSource> file,
|
||||
QPDF& qpdf_for_warning, Pipeline*& pipeline,
|
||||
int objid, int generation,
|
||||
QPDFObjectHandle& stream_dict,
|
||||
std::vector<std::shared_ptr<Pipeline>>& heap)
|
||||
QPDFObjectHandle& stream_dict,
|
||||
std::vector<std::shared_ptr<Pipeline>>& heap)
|
||||
{
|
||||
std::string type;
|
||||
if (stream_dict.getKey("/Type").isName())
|
||||
{
|
||||
type = stream_dict.getKey("/Type").getName();
|
||||
type = stream_dict.getKey("/Type").getName();
|
||||
}
|
||||
if (type == "/XRef")
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file");
|
||||
return;
|
||||
QTC::TC("qpdf", "QPDF_encryption xref stream from encrypted file");
|
||||
return;
|
||||
}
|
||||
bool use_aes = false;
|
||||
if (encp->encryption_V >= 4)
|
||||
{
|
||||
encryption_method_e method = e_unknown;
|
||||
std::string method_source = "/StmF from /Encrypt dictionary";
|
||||
encryption_method_e method = e_unknown;
|
||||
std::string method_source = "/StmF from /Encrypt dictionary";
|
||||
|
||||
if (stream_dict.getKey("/Filter").isOrHasName("/Crypt"))
|
||||
if (stream_dict.getKey("/Filter").isOrHasName("/Crypt"))
|
||||
{
|
||||
if (stream_dict.getKey("/DecodeParms").isDictionary())
|
||||
{
|
||||
@ -1294,67 +1294,67 @@ QPDF::decryptStream(PointerHolder<EncryptionParameters> encp,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (method == e_unknown)
|
||||
{
|
||||
if ((! encp->encrypt_metadata) && (type == "/Metadata"))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption cleartext metadata");
|
||||
method = e_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (method == e_unknown)
|
||||
{
|
||||
if ((! encp->encrypt_metadata) && (type == "/Metadata"))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption cleartext metadata");
|
||||
method = e_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
method = encp->cf_stream;
|
||||
}
|
||||
}
|
||||
use_aes = false;
|
||||
switch (method)
|
||||
{
|
||||
case e_none:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
use_aes = false;
|
||||
switch (method)
|
||||
{
|
||||
case e_none:
|
||||
return;
|
||||
break;
|
||||
|
||||
case e_aes:
|
||||
use_aes = true;
|
||||
break;
|
||||
case e_aes:
|
||||
use_aes = true;
|
||||
break;
|
||||
|
||||
case e_aesv3:
|
||||
use_aes = true;
|
||||
break;
|
||||
case e_aesv3:
|
||||
use_aes = true;
|
||||
break;
|
||||
|
||||
case e_rc4:
|
||||
break;
|
||||
case e_rc4:
|
||||
break;
|
||||
|
||||
default:
|
||||
// filter local to this stream.
|
||||
qpdf_for_warning.warn(
|
||||
default:
|
||||
// filter local to this stream.
|
||||
qpdf_for_warning.warn(
|
||||
QPDFExc(qpdf_e_damaged_pdf, file->getName(),
|
||||
"", file->getLastOffset(),
|
||||
"unknown encryption filter for streams"
|
||||
" (check " + method_source + ");"
|
||||
" streams may be decrypted improperly"));
|
||||
// To avoid repeated warnings, reset cf_stream. Assume
|
||||
// we'd want to use AES if V == 4.
|
||||
encp->cf_stream = e_aes;
|
||||
// To avoid repeated warnings, reset cf_stream. Assume
|
||||
// we'd want to use AES if V == 4.
|
||||
encp->cf_stream = e_aes;
|
||||
use_aes = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string key = getKeyForObject(encp, objid, generation, use_aes);
|
||||
std::shared_ptr<Pipeline> new_pipeline;
|
||||
if (use_aes)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption aes decode stream");
|
||||
new_pipeline = std::make_shared<Pl_AES_PDF>(
|
||||
QTC::TC("qpdf", "QPDF_encryption aes decode stream");
|
||||
new_pipeline = std::make_shared<Pl_AES_PDF>(
|
||||
"AES stream decryption", pipeline,
|
||||
false, QUtil::unsigned_char_pointer(key),
|
||||
key.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");
|
||||
new_pipeline = std::make_shared<Pl_RC4>(
|
||||
QTC::TC("qpdf", "QPDF_encryption rc4 decode stream");
|
||||
new_pipeline = std::make_shared<Pl_RC4>(
|
||||
"RC4 stream decryption", pipeline,
|
||||
QUtil::unsigned_char_pointer(key),
|
||||
toI(key.length()));
|
||||
@ -1371,8 +1371,8 @@ QPDF::compute_encryption_O_U(
|
||||
{
|
||||
if (V >= 5)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"compute_encryption_O_U called for file with V >= 5");
|
||||
throw std::logic_error(
|
||||
"compute_encryption_O_U called for file with V >= 5");
|
||||
}
|
||||
EncryptionData data(V, R, key_len, P, "", "", "", "", "",
|
||||
id1, encrypt_metadata);
|
||||
@ -1444,22 +1444,22 @@ QPDF::isEncrypted(int& R, int& P, int& V,
|
||||
{
|
||||
if (this->m->encp->encrypted)
|
||||
{
|
||||
QPDFObjectHandle trailer = getTrailer();
|
||||
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
|
||||
QPDFObjectHandle Pkey = encrypt.getKey("/P");
|
||||
QPDFObjectHandle Rkey = encrypt.getKey("/R");
|
||||
QPDFObjectHandle trailer = getTrailer();
|
||||
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
|
||||
QPDFObjectHandle Pkey = encrypt.getKey("/P");
|
||||
QPDFObjectHandle Rkey = encrypt.getKey("/R");
|
||||
QPDFObjectHandle Vkey = encrypt.getKey("/V");
|
||||
P = static_cast<int>(Pkey.getIntValue());
|
||||
R = Rkey.getIntValueAsInt();
|
||||
P = static_cast<int>(Pkey.getIntValue());
|
||||
R = Rkey.getIntValueAsInt();
|
||||
V = Vkey.getIntValueAsInt();
|
||||
stream_method = this->m->encp->cf_stream;
|
||||
string_method = this->m->encp->cf_string;
|
||||
file_method = this->m->encp->cf_file;
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1490,14 +1490,14 @@ QPDF::allowAccessibility()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
if (R < 3)
|
||||
{
|
||||
status = is_bit_set(P, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = is_bit_set(P, 10);
|
||||
}
|
||||
if (R < 3)
|
||||
{
|
||||
status = is_bit_set(P, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = is_bit_set(P, 10);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1510,7 +1510,7 @@ QPDF::allowExtractAll()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
status = is_bit_set(P, 5);
|
||||
status = is_bit_set(P, 5);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1523,7 +1523,7 @@ QPDF::allowPrintLowRes()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
status = is_bit_set(P, 3);
|
||||
status = is_bit_set(P, 3);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1536,11 +1536,11 @@ QPDF::allowPrintHighRes()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
status = is_bit_set(P, 3);
|
||||
if ((R >= 3) && (! is_bit_set(P, 12)))
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
status = is_bit_set(P, 3);
|
||||
if ((R >= 3) && (! is_bit_set(P, 12)))
|
||||
{
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1553,14 +1553,14 @@ QPDF::allowModifyAssembly()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
if (R < 3)
|
||||
{
|
||||
status = is_bit_set(P, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = is_bit_set(P, 11);
|
||||
}
|
||||
if (R < 3)
|
||||
{
|
||||
status = is_bit_set(P, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = is_bit_set(P, 11);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1573,14 +1573,14 @@ QPDF::allowModifyForm()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
if (R < 3)
|
||||
{
|
||||
status = is_bit_set(P, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = is_bit_set(P, 9);
|
||||
}
|
||||
if (R < 3)
|
||||
{
|
||||
status = is_bit_set(P, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = is_bit_set(P, 9);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1593,7 +1593,7 @@ QPDF::allowModifyAnnotation()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
status = is_bit_set(P, 6);
|
||||
status = is_bit_set(P, 6);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1606,7 +1606,7 @@ QPDF::allowModifyOther()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
status = is_bit_set(P, 4);
|
||||
status = is_bit_set(P, 4);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -1619,11 +1619,11 @@ QPDF::allowModifyAll()
|
||||
bool status = true;
|
||||
if (isEncrypted(R, P))
|
||||
{
|
||||
status = (is_bit_set(P, 4) && is_bit_set(P, 6));
|
||||
if (R >= 3)
|
||||
{
|
||||
status = status && (is_bit_set(P, 9) && is_bit_set(P, 11));
|
||||
}
|
||||
status = (is_bit_set(P, 4) && is_bit_set(P, 6));
|
||||
if (R >= 3)
|
||||
{
|
||||
status = status && (is_bit_set(P, 9) && is_bit_set(P, 11));
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -41,18 +41,18 @@ QPDF::ObjUser::operator<(ObjUser const& rhs) const
|
||||
{
|
||||
if (this->ou_type < rhs.ou_type)
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else if (this->ou_type == rhs.ou_type)
|
||||
{
|
||||
if (this->pageno < rhs.pageno)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this->pageno == rhs.pageno)
|
||||
{
|
||||
return (this->key < rhs.key);
|
||||
}
|
||||
if (this->pageno < rhs.pageno)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (this->pageno == rhs.pageno)
|
||||
{
|
||||
return (this->key < rhs.key);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -60,20 +60,20 @@ QPDF::ObjUser::operator<(ObjUser const& rhs) const
|
||||
|
||||
void
|
||||
QPDF::optimize(std::map<int, int> const& object_stream_data,
|
||||
bool allow_changes)
|
||||
bool allow_changes)
|
||||
{
|
||||
optimize(object_stream_data, allow_changes, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::optimize(std::map<int, int> const& object_stream_data,
|
||||
bool allow_changes,
|
||||
bool allow_changes,
|
||||
std::function<int(QPDFObjectHandle&)> skip_stream_parameters)
|
||||
{
|
||||
if (! this->m->obj_user_to_objects.empty())
|
||||
{
|
||||
// already optimized
|
||||
return;
|
||||
// already optimized
|
||||
return;
|
||||
}
|
||||
|
||||
// The PDF specification indicates that /Outlines is supposed to
|
||||
@ -106,35 +106,35 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
|
||||
// Traverse document-level items
|
||||
std::set<std::string> keys = this->m->trailer.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = *iter;
|
||||
if (key == "/Root")
|
||||
{
|
||||
// handled separately
|
||||
}
|
||||
else
|
||||
{
|
||||
updateObjectMaps(ObjUser(ObjUser::ou_trailer_key, key),
|
||||
this->m->trailer.getKey(key),
|
||||
std::string const& key = *iter;
|
||||
if (key == "/Root")
|
||||
{
|
||||
// handled separately
|
||||
}
|
||||
else
|
||||
{
|
||||
updateObjectMaps(ObjUser(ObjUser::ou_trailer_key, key),
|
||||
this->m->trailer.getKey(key),
|
||||
skip_stream_parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys = root.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
// Technically, /I keys from /Thread dictionaries are supposed
|
||||
// to be handled separately, but we are going to disregard
|
||||
// that specification for now. There is loads of evidence
|
||||
// that pdlin and Acrobat both disregard things like this from
|
||||
// time to time, so this is almost certain not to cause any
|
||||
// problems.
|
||||
// Technically, /I keys from /Thread dictionaries are supposed
|
||||
// to be handled separately, but we are going to disregard
|
||||
// that specification for now. There is loads of evidence
|
||||
// that pdlin and Acrobat both disregard things like this from
|
||||
// time to time, so this is almost certain not to cause any
|
||||
// problems.
|
||||
|
||||
std::string const& key = *iter;
|
||||
updateObjectMaps(ObjUser(ObjUser::ou_root_key, key),
|
||||
root.getKey(key),
|
||||
std::string const& key = *iter;
|
||||
updateObjectMaps(ObjUser(ObjUser::ou_root_key, key),
|
||||
root.getKey(key),
|
||||
skip_stream_parameters);
|
||||
}
|
||||
|
||||
@ -208,10 +208,10 @@ QPDF::pushInheritedAttributesToPageInternal(
|
||||
|
||||
if (! cur_pages.isDictionary())
|
||||
{
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"invalid object in page tree");
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"invalid object in page tree");
|
||||
}
|
||||
|
||||
// Extract the underlying dictionary object
|
||||
@ -219,60 +219,60 @@ QPDF::pushInheritedAttributesToPageInternal(
|
||||
|
||||
if (type == "/Pages")
|
||||
{
|
||||
// Make a list of inheritable keys. Only the keys /MediaBox,
|
||||
// /CropBox, /Resources, and /Rotate are inheritable
|
||||
// attributes. Push this object onto the stack of pages nodes
|
||||
// that have values for this attribute.
|
||||
// Make a list of inheritable keys. Only the keys /MediaBox,
|
||||
// /CropBox, /Resources, and /Rotate are inheritable
|
||||
// attributes. Push this object onto the stack of pages nodes
|
||||
// that have values for this attribute.
|
||||
|
||||
std::set<std::string> inheritable_keys;
|
||||
std::set<std::string> keys = cur_pages.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = *iter;
|
||||
std::set<std::string> inheritable_keys;
|
||||
std::set<std::string> keys = cur_pages.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = *iter;
|
||||
if ( (key == "/MediaBox") || (key == "/CropBox") ||
|
||||
(key == "/Resources") || (key == "/Rotate") )
|
||||
{
|
||||
if (! allow_changes)
|
||||
{
|
||||
throw QPDFExc(qpdf_e_internal, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"optimize detected an "
|
||||
{
|
||||
if (! allow_changes)
|
||||
{
|
||||
throw QPDFExc(qpdf_e_internal, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"optimize detected an "
|
||||
"inheritable attribute when called "
|
||||
"in no-change mode");
|
||||
}
|
||||
"in no-change mode");
|
||||
}
|
||||
|
||||
// This is an inheritable resource
|
||||
inheritable_keys.insert(key);
|
||||
QPDFObjectHandle oh = cur_pages.getKey(key);
|
||||
QTC::TC("qpdf", "QPDF opt direct pages resource",
|
||||
oh.isIndirect() ? 0 : 1);
|
||||
if (! oh.isIndirect())
|
||||
{
|
||||
if (! oh.isScalar())
|
||||
{
|
||||
// Replace shared direct object non-scalar
|
||||
// resources with indirect objects to avoid
|
||||
// copying large structures around.
|
||||
cur_pages.replaceKey(key, makeIndirectObject(oh));
|
||||
oh = cur_pages.getKey(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's okay to copy scalars.
|
||||
QTC::TC("qpdf", "QPDF opt inherited scalar");
|
||||
}
|
||||
}
|
||||
key_ancestors[key].push_back(oh);
|
||||
if (key_ancestors[key].size() > 1)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt key ancestors depth > 1");
|
||||
}
|
||||
// Remove this resource from this node. It will be
|
||||
// reattached at the page level.
|
||||
cur_pages.removeKey(key);
|
||||
}
|
||||
// This is an inheritable resource
|
||||
inheritable_keys.insert(key);
|
||||
QPDFObjectHandle oh = cur_pages.getKey(key);
|
||||
QTC::TC("qpdf", "QPDF opt direct pages resource",
|
||||
oh.isIndirect() ? 0 : 1);
|
||||
if (! oh.isIndirect())
|
||||
{
|
||||
if (! oh.isScalar())
|
||||
{
|
||||
// Replace shared direct object non-scalar
|
||||
// resources with indirect objects to avoid
|
||||
// copying large structures around.
|
||||
cur_pages.replaceKey(key, makeIndirectObject(oh));
|
||||
oh = cur_pages.getKey(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's okay to copy scalars.
|
||||
QTC::TC("qpdf", "QPDF opt inherited scalar");
|
||||
}
|
||||
}
|
||||
key_ancestors[key].push_back(oh);
|
||||
if (key_ancestors[key].size() > 1)
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt key ancestors depth > 1");
|
||||
}
|
||||
// Remove this resource from this node. It will be
|
||||
// reattached at the page level.
|
||||
cur_pages.removeKey(key);
|
||||
}
|
||||
else if (! ((key == "/Type") || (key == "/Parent") ||
|
||||
(key == "/Kids") || (key == "/Count")))
|
||||
{
|
||||
@ -292,71 +292,71 @@ QPDF::pushInheritedAttributesToPageInternal(
|
||||
" flattening the /Pages tree"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Visit descendant nodes.
|
||||
QPDFObjectHandle kids = cur_pages.getKey("/Kids");
|
||||
int n = kids.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
// Visit descendant nodes.
|
||||
QPDFObjectHandle kids = cur_pages.getKey("/Kids");
|
||||
int n = kids.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
pushInheritedAttributesToPageInternal(
|
||||
kids.getArrayItem(i), key_ancestors, pages,
|
||||
allow_changes, warn_skipped_keys, visited);
|
||||
}
|
||||
}
|
||||
|
||||
// For each inheritable key, pop the stack. If the stack
|
||||
// becomes empty, remove it from the map. That way, the
|
||||
// invariant that the list of keys in key_ancestors is exactly
|
||||
// those keys for which inheritable attributes are available.
|
||||
// For each inheritable key, pop the stack. If the stack
|
||||
// becomes empty, remove it from the map. That way, the
|
||||
// invariant that the list of keys in key_ancestors is exactly
|
||||
// those keys for which inheritable attributes are available.
|
||||
|
||||
if (! inheritable_keys.empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt inheritable keys");
|
||||
for (std::set<std::string>::iterator iter =
|
||||
inheritable_keys.begin();
|
||||
iter != inheritable_keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = (*iter);
|
||||
key_ancestors[key].pop_back();
|
||||
if (key_ancestors[key].empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt erase empty key ancestor");
|
||||
key_ancestors.erase(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt no inheritable keys");
|
||||
}
|
||||
if (! inheritable_keys.empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt inheritable keys");
|
||||
for (std::set<std::string>::iterator iter =
|
||||
inheritable_keys.begin();
|
||||
iter != inheritable_keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = (*iter);
|
||||
key_ancestors[key].pop_back();
|
||||
if (key_ancestors[key].empty())
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt erase empty key ancestor");
|
||||
key_ancestors.erase(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt no inheritable keys");
|
||||
}
|
||||
}
|
||||
else if (type == "/Page")
|
||||
{
|
||||
// Add all available inheritable attributes not present in
|
||||
// this object to this object.
|
||||
for (std::map<std::string, std::vector<QPDFObjectHandle> >::iterator
|
||||
iter = key_ancestors.begin();
|
||||
iter != key_ancestors.end(); ++iter)
|
||||
{
|
||||
std::string const& key = (*iter).first;
|
||||
if (! cur_pages.hasKey(key))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt resource inherited");
|
||||
cur_pages.replaceKey(key, (*iter).second.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt page resource hides ancestor");
|
||||
}
|
||||
}
|
||||
// Add all available inheritable attributes not present in
|
||||
// this object to this object.
|
||||
for (std::map<std::string, std::vector<QPDFObjectHandle> >::iterator
|
||||
iter = key_ancestors.begin();
|
||||
iter != key_ancestors.end(); ++iter)
|
||||
{
|
||||
std::string const& key = (*iter).first;
|
||||
if (! cur_pages.hasKey(key))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt resource inherited");
|
||||
cur_pages.replaceKey(key, (*iter).second.back());
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt page resource hides ancestor");
|
||||
}
|
||||
}
|
||||
pages.push_back(cur_pages);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"invalid Type " + type + " in page tree");
|
||||
throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
|
||||
this->m->last_object_description,
|
||||
this->m->file->getLastOffset(),
|
||||
"invalid Type " + type + " in page tree");
|
||||
}
|
||||
visited.erase(this_og);
|
||||
}
|
||||
@ -393,59 +393,59 @@ QPDF::updateObjectMapsInternal(
|
||||
|
||||
if (oh.isIndirect())
|
||||
{
|
||||
QPDFObjGen og(oh.getObjGen());
|
||||
if (visited.count(og))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt loop detected");
|
||||
return;
|
||||
}
|
||||
this->m->obj_user_to_objects[ou].insert(og);
|
||||
this->m->object_to_obj_users[og].insert(ou);
|
||||
visited.insert(og);
|
||||
QPDFObjGen og(oh.getObjGen());
|
||||
if (visited.count(og))
|
||||
{
|
||||
QTC::TC("qpdf", "QPDF opt loop detected");
|
||||
return;
|
||||
}
|
||||
this->m->obj_user_to_objects[ou].insert(og);
|
||||
this->m->object_to_obj_users[og].insert(ou);
|
||||
visited.insert(og);
|
||||
}
|
||||
|
||||
if (oh.isArray())
|
||||
{
|
||||
int n = oh.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
updateObjectMapsInternal(
|
||||
int n = oh.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
updateObjectMapsInternal(
|
||||
ou, oh.getArrayItem(i), skip_stream_parameters,
|
||||
visited, false, 1 + depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (oh.isDictionary() || oh.isStream())
|
||||
{
|
||||
QPDFObjectHandle dict = oh;
|
||||
QPDFObjectHandle dict = oh;
|
||||
bool is_stream = oh.isStream();
|
||||
int ssp = 0;
|
||||
if (is_stream)
|
||||
{
|
||||
dict = oh.getDict();
|
||||
if (is_stream)
|
||||
{
|
||||
dict = oh.getDict();
|
||||
if (skip_stream_parameters)
|
||||
{
|
||||
ssp = skip_stream_parameters(oh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::string> keys = dict.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = *iter;
|
||||
if (is_page_node && (key == "/Thumb"))
|
||||
{
|
||||
// Traverse page thumbnail dictionaries as a special
|
||||
// case.
|
||||
updateObjectMapsInternal(
|
||||
std::set<std::string> keys = dict.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
{
|
||||
std::string const& key = *iter;
|
||||
if (is_page_node && (key == "/Thumb"))
|
||||
{
|
||||
// Traverse page thumbnail dictionaries as a special
|
||||
// case.
|
||||
updateObjectMapsInternal(
|
||||
ObjUser(ObjUser::ou_thumb, ou.pageno),
|
||||
dict.getKey(key), skip_stream_parameters,
|
||||
visited, false, 1 + depth);
|
||||
}
|
||||
else if (is_page_node && (key == "/Parent"))
|
||||
{
|
||||
// Don't traverse back up the page tree
|
||||
}
|
||||
}
|
||||
else if (is_page_node && (key == "/Parent"))
|
||||
{
|
||||
// Don't traverse back up the page tree
|
||||
}
|
||||
else if (((ssp >= 1) && (key == "/Length")) ||
|
||||
((ssp >= 2) && ((key == "/Filter") ||
|
||||
(key == "/DecodeParms"))))
|
||||
@ -453,13 +453,13 @@ QPDF::updateObjectMapsInternal(
|
||||
// Don't traverse into stream parameters that we are
|
||||
// not going to write.
|
||||
}
|
||||
else
|
||||
{
|
||||
updateObjectMapsInternal(
|
||||
else
|
||||
{
|
||||
updateObjectMapsInternal(
|
||||
ou, dict.getKey(key), skip_stream_parameters,
|
||||
visited, false, 1 + depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,7 +468,7 @@ QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data)
|
||||
{
|
||||
if (object_stream_data.empty())
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// Transform object_to_obj_users and obj_user_to_objects so that
|
||||
@ -480,49 +480,49 @@ QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data)
|
||||
std::map<QPDFObjGen, std::set<ObjUser> > t_object_to_obj_users;
|
||||
|
||||
for (std::map<ObjUser, std::set<QPDFObjGen> >::iterator i1 =
|
||||
this->m->obj_user_to_objects.begin();
|
||||
i1 != this->m->obj_user_to_objects.end(); ++i1)
|
||||
this->m->obj_user_to_objects.begin();
|
||||
i1 != this->m->obj_user_to_objects.end(); ++i1)
|
||||
{
|
||||
ObjUser const& ou = (*i1).first;
|
||||
std::set<QPDFObjGen> const& objects = (*i1).second;
|
||||
for (std::set<QPDFObjGen>::const_iterator i2 = objects.begin();
|
||||
i2 != objects.end(); ++i2)
|
||||
{
|
||||
QPDFObjGen const& og = (*i2);
|
||||
std::map<int, int>::const_iterator i3 =
|
||||
object_stream_data.find(og.getObj());
|
||||
if (i3 == object_stream_data.end())
|
||||
{
|
||||
t_obj_user_to_objects[ou].insert(og);
|
||||
}
|
||||
else
|
||||
{
|
||||
t_obj_user_to_objects[ou].insert(QPDFObjGen((*i3).second, 0));
|
||||
}
|
||||
}
|
||||
ObjUser const& ou = (*i1).first;
|
||||
std::set<QPDFObjGen> const& objects = (*i1).second;
|
||||
for (std::set<QPDFObjGen>::const_iterator i2 = objects.begin();
|
||||
i2 != objects.end(); ++i2)
|
||||
{
|
||||
QPDFObjGen const& og = (*i2);
|
||||
std::map<int, int>::const_iterator i3 =
|
||||
object_stream_data.find(og.getObj());
|
||||
if (i3 == object_stream_data.end())
|
||||
{
|
||||
t_obj_user_to_objects[ou].insert(og);
|
||||
}
|
||||
else
|
||||
{
|
||||
t_obj_user_to_objects[ou].insert(QPDFObjGen((*i3).second, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::map<QPDFObjGen, std::set<ObjUser> >::iterator i1 =
|
||||
this->m->object_to_obj_users.begin();
|
||||
i1 != this->m->object_to_obj_users.end(); ++i1)
|
||||
this->m->object_to_obj_users.begin();
|
||||
i1 != this->m->object_to_obj_users.end(); ++i1)
|
||||
{
|
||||
QPDFObjGen const& og = (*i1).first;
|
||||
std::set<ObjUser> const& objusers = (*i1).second;
|
||||
for (std::set<ObjUser>::const_iterator i2 = objusers.begin();
|
||||
i2 != objusers.end(); ++i2)
|
||||
{
|
||||
ObjUser const& ou = (*i2);
|
||||
std::map<int, int>::const_iterator i3 =
|
||||
object_stream_data.find(og.getObj());
|
||||
if (i3 == object_stream_data.end())
|
||||
{
|
||||
t_object_to_obj_users[og].insert(ou);
|
||||
}
|
||||
else
|
||||
{
|
||||
t_object_to_obj_users[QPDFObjGen((*i3).second, 0)].insert(ou);
|
||||
}
|
||||
}
|
||||
QPDFObjGen const& og = (*i1).first;
|
||||
std::set<ObjUser> const& objusers = (*i1).second;
|
||||
for (std::set<ObjUser>::const_iterator i2 = objusers.begin();
|
||||
i2 != objusers.end(); ++i2)
|
||||
{
|
||||
ObjUser const& ou = (*i2);
|
||||
std::map<int, int>::const_iterator i3 =
|
||||
object_stream_data.find(og.getObj());
|
||||
if (i3 == object_stream_data.end())
|
||||
{
|
||||
t_object_to_obj_users[og].insert(ou);
|
||||
}
|
||||
else
|
||||
{
|
||||
t_object_to_obj_users[QPDFObjGen((*i3).second, 0)].insert(ou);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->m->obj_user_to_objects = t_obj_user_to_objects;
|
||||
|
@ -86,7 +86,7 @@ QPDF::getAllPages()
|
||||
getRoot().replaceKey("/Pages", pages);
|
||||
}
|
||||
seen.clear();
|
||||
getAllPagesInternal(pages, this->m->all_pages, visited, seen);
|
||||
getAllPagesInternal(pages, this->m->all_pages, visited, seen);
|
||||
}
|
||||
return this->m->all_pages;
|
||||
}
|
||||
@ -110,10 +110,10 @@ QPDF::getAllPagesInternal(QPDFObjectHandle cur_node,
|
||||
if (cur_node.hasKey("/Kids"))
|
||||
{
|
||||
wanted_type = "/Pages";
|
||||
QPDFObjectHandle kids = cur_node.getKey("/Kids");
|
||||
int n = kids.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
QPDFObjectHandle kids = cur_node.getKey("/Kids");
|
||||
int n = kids.getArrayNItems();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
QPDFObjectHandle kid = kids.getArrayItem(i);
|
||||
if (! kid.isIndirect())
|
||||
{
|
||||
@ -129,14 +129,14 @@ QPDF::getAllPagesInternal(QPDFObjectHandle cur_node,
|
||||
kid = makeIndirectObject(QPDFObjectHandle(kid).shallowCopy());
|
||||
kids.setArrayItem(i, kid);
|
||||
}
|
||||
getAllPagesInternal(kid, result, visited, seen);
|
||||
}
|
||||
getAllPagesInternal(kid, result, visited, seen);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wanted_type = "/Page";
|
||||
seen.insert(this_og);
|
||||
result.push_back(cur_node);
|
||||
result.push_back(cur_node);
|
||||
}
|
||||
|
||||
if (! cur_node.isDictionaryOfType(wanted_type))
|
||||
|
@ -16,7 +16,7 @@ void QTC::TC(char const* const scope, char const* const ccase, int n)
|
||||
|
||||
if (! tc_active(scope))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
@ -27,13 +27,13 @@ void QTC::TC(char const* const scope, char const* const ccase, int n)
|
||||
#endif
|
||||
if (! QUtil::get_env(TC_ENV, &filename))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
#undef TC_ENV
|
||||
|
||||
if (cache.count(std::make_pair(ccase, n)))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
cache.insert(std::make_pair(ccase, n));
|
||||
|
||||
|
108
libqpdf/QUtil.cc
108
libqpdf/QUtil.cc
@ -300,12 +300,12 @@ int_to_string_base_internal(T num, int base, int length)
|
||||
int str_length = QIntC::to_int(cvt.length());
|
||||
if ((length > 0) && (str_length < length))
|
||||
{
|
||||
result.append(QIntC::to_size(length - str_length), '0');
|
||||
result.append(QIntC::to_size(length - str_length), '0');
|
||||
}
|
||||
result += cvt;
|
||||
if ((length < 0) && (str_length < -length))
|
||||
{
|
||||
result.append(QIntC::to_size(-length - str_length), ' ');
|
||||
result.append(QIntC::to_size(-length - str_length), ' ');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -455,7 +455,7 @@ QUtil::os_wrapper(std::string const& description, int status)
|
||||
{
|
||||
if (status == -1)
|
||||
{
|
||||
throw_system_error(description);
|
||||
throw_system_error(description);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -523,7 +523,7 @@ QUtil::fopen_wrapper(std::string const& description, FILE* f)
|
||||
{
|
||||
if (f == 0)
|
||||
{
|
||||
throw_system_error(description);
|
||||
throw_system_error(description);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
@ -841,17 +841,17 @@ QUtil::getWhoami(char* argv0)
|
||||
if (((whoami = strrchr(argv0, '/')) == NULL) &&
|
||||
((whoami = strrchr(argv0, '\\')) == NULL))
|
||||
{
|
||||
whoami = argv0;
|
||||
whoami = argv0;
|
||||
}
|
||||
else
|
||||
{
|
||||
++whoami;
|
||||
++whoami;
|
||||
}
|
||||
|
||||
if ((strlen(whoami) > 4) &&
|
||||
(strcmp(whoami + strlen(whoami) - 4, ".exe") == 0))
|
||||
(strcmp(whoami + strlen(whoami) - 4, ".exe") == 0))
|
||||
{
|
||||
whoami[strlen(whoami) - 4] = '\0';
|
||||
whoami[strlen(whoami) - 4] = '\0';
|
||||
}
|
||||
|
||||
return whoami;
|
||||
@ -875,9 +875,9 @@ QUtil::get_env(std::string const& var, std::string* value)
|
||||
|
||||
if (value)
|
||||
{
|
||||
PointerHolder<char> t = PointerHolder<char>(true, new char[len + 1]);
|
||||
PointerHolder<char> t = PointerHolder<char>(true, new char[len + 1]);
|
||||
::GetEnvironmentVariable(var.c_str(), t.get(), len);
|
||||
*value = t.get();
|
||||
*value = t.get();
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1057,42 +1057,42 @@ QUtil::toUTF8(unsigned long uval)
|
||||
|
||||
if (uval > 0x7fffffff)
|
||||
{
|
||||
throw std::runtime_error("bounds error in QUtil::toUTF8");
|
||||
throw std::runtime_error("bounds error in QUtil::toUTF8");
|
||||
}
|
||||
else if (uval < 128)
|
||||
{
|
||||
result += static_cast<char>(uval);
|
||||
result += static_cast<char>(uval);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char bytes[7];
|
||||
bytes[6] = '\0';
|
||||
unsigned char* cur_byte = &bytes[5];
|
||||
unsigned char bytes[7];
|
||||
bytes[6] = '\0';
|
||||
unsigned char* cur_byte = &bytes[5];
|
||||
|
||||
// maximum value that will fit in the current number of bytes
|
||||
unsigned char maxval = 0x3f; // six bits
|
||||
// maximum value that will fit in the current number of bytes
|
||||
unsigned char maxval = 0x3f; // six bits
|
||||
|
||||
while (uval > QIntC::to_ulong(maxval))
|
||||
{
|
||||
// Assign low six bits plus 10000000 to lowest unused
|
||||
// byte position, then shift
|
||||
*cur_byte = static_cast<unsigned char>(0x80 + (uval & 0x3f));
|
||||
uval >>= 6;
|
||||
// Maximum that will fit in high byte now shrinks by one bit
|
||||
maxval = static_cast<unsigned char>(maxval >> 1);
|
||||
// Slide to the left one byte
|
||||
if (cur_byte <= bytes)
|
||||
{
|
||||
throw std::logic_error("QUtil::toUTF8: overflow error");
|
||||
}
|
||||
--cur_byte;
|
||||
}
|
||||
// If maxval is k bits long, the high (7 - k) bits of the
|
||||
// resulting byte must be high.
|
||||
*cur_byte = static_cast<unsigned char>(
|
||||
while (uval > QIntC::to_ulong(maxval))
|
||||
{
|
||||
// Assign low six bits plus 10000000 to lowest unused
|
||||
// byte position, then shift
|
||||
*cur_byte = static_cast<unsigned char>(0x80 + (uval & 0x3f));
|
||||
uval >>= 6;
|
||||
// Maximum that will fit in high byte now shrinks by one bit
|
||||
maxval = static_cast<unsigned char>(maxval >> 1);
|
||||
// Slide to the left one byte
|
||||
if (cur_byte <= bytes)
|
||||
{
|
||||
throw std::logic_error("QUtil::toUTF8: overflow error");
|
||||
}
|
||||
--cur_byte;
|
||||
}
|
||||
// If maxval is k bits long, the high (7 - k) bits of the
|
||||
// resulting byte must be high.
|
||||
*cur_byte = static_cast<unsigned char>(
|
||||
QIntC::to_ulong(0xff - (1 + (maxval << 1))) + uval);
|
||||
|
||||
result += reinterpret_cast<char*>(cur_byte);
|
||||
result += reinterpret_cast<char*>(cur_byte);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1350,19 +1350,19 @@ QUtil::read_lines_from_file(std::function<bool(char&)> next_char,
|
||||
char c;
|
||||
while (next_char(c))
|
||||
{
|
||||
if (buf == 0)
|
||||
{
|
||||
lines.push_back("");
|
||||
buf = &(lines.back());
|
||||
buf->reserve(80);
|
||||
}
|
||||
if (buf == 0)
|
||||
{
|
||||
lines.push_back("");
|
||||
buf = &(lines.back());
|
||||
buf->reserve(80);
|
||||
}
|
||||
|
||||
if (buf->capacity() == buf->size())
|
||||
{
|
||||
buf->reserve(buf->capacity() * 2);
|
||||
}
|
||||
if (c == '\n')
|
||||
{
|
||||
if (buf->capacity() == buf->size())
|
||||
{
|
||||
buf->reserve(buf->capacity() * 2);
|
||||
}
|
||||
if (c == '\n')
|
||||
{
|
||||
if (preserve_eol)
|
||||
{
|
||||
buf->append(1, c);
|
||||
@ -1376,12 +1376,12 @@ QUtil::read_lines_from_file(std::function<bool(char&)> next_char,
|
||||
buf->erase(buf->length() - 1);
|
||||
}
|
||||
}
|
||||
buf = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->append(1, c);
|
||||
}
|
||||
buf = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->append(1, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ RC4_native::RC4_native(unsigned char const* key_data, int key_len)
|
||||
{
|
||||
if (key_len == -1)
|
||||
{
|
||||
key_len = QIntC::to_int(
|
||||
key_len = QIntC::to_int(
|
||||
strlen(reinterpret_cast<char const*>(key_data)));
|
||||
}
|
||||
|
||||
@ -32,9 +32,9 @@ RC4_native::RC4_native(unsigned char const* key_data, int key_len)
|
||||
int i2 = 0;
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
i2 = (key_data[i1] + key.state[i] + i2) % 256;
|
||||
swap_byte(key.state[i], key.state[i2]);
|
||||
i1 = (i1 + 1) % key_len;
|
||||
i2 = (key_data[i1] + key.state[i] + i2) % 256;
|
||||
swap_byte(key.state[i], key.state[i2]);
|
||||
i1 = (i1 + 1) % key_len;
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,16 +43,16 @@ RC4_native::process(unsigned char *in_data, size_t len, unsigned char* out_data)
|
||||
{
|
||||
if (out_data == 0)
|
||||
{
|
||||
// Convert in place
|
||||
out_data = in_data;
|
||||
// Convert in place
|
||||
out_data = in_data;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
key.x = static_cast<unsigned char>((key.x + 1) % 256);
|
||||
key.y = static_cast<unsigned char>((key.state[key.x] + key.y) % 256);
|
||||
swap_byte(key.state[key.x], key.state[key.y]);
|
||||
int xor_index = (key.state[key.x] + key.state[key.y]) % 256;
|
||||
out_data[i] = in_data[i] ^ key.state[xor_index];
|
||||
key.x = static_cast<unsigned char>((key.x + 1) % 256);
|
||||
key.y = static_cast<unsigned char>((key.state[key.x] + key.y) % 256);
|
||||
swap_byte(key.state[key.x], key.state[key.y]);
|
||||
int xor_index = (key.state[key.x] + key.state[key.y]) % 256;
|
||||
out_data[i] = in_data[i] ^ key.state[xor_index];
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
|
||||
|
||||
if ((this->predictor > 1) && (this->columns == 0))
|
||||
{
|
||||
filterable = false;
|
||||
filterable = false;
|
||||
}
|
||||
|
||||
return filterable;
|
||||
|
@ -28,8 +28,8 @@ SparseOHArray::at(size_t idx) const
|
||||
{
|
||||
if (idx >= this->n_elements)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing SparseOHArray element");
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: bounds error accessing SparseOHArray element");
|
||||
}
|
||||
auto const& iter = this->elements.find(idx);
|
||||
if (iter == this->elements.end())
|
||||
@ -47,8 +47,8 @@ SparseOHArray::remove_last()
|
||||
{
|
||||
if (this->n_elements == 0)
|
||||
{
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: attempt to remove"
|
||||
throw std::logic_error(
|
||||
"INTERNAL ERROR: attempt to remove"
|
||||
" last item from empty SparseOHArray");
|
||||
}
|
||||
--this->n_elements;
|
||||
@ -60,7 +60,7 @@ SparseOHArray::releaseResolved()
|
||||
{
|
||||
for (auto& iter: this->elements)
|
||||
{
|
||||
QPDFObjectHandle::ReleaseResolver::releaseResolved(iter.second);
|
||||
QPDFObjectHandle::ReleaseResolver::releaseResolved(iter.second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ SparseOHArray::setAt(size_t idx, QPDFObjectHandle oh)
|
||||
{
|
||||
if (idx >= this->n_elements)
|
||||
{
|
||||
throw std::logic_error("bounds error setting item in SparseOHArray");
|
||||
throw std::logic_error("bounds error setting item in SparseOHArray");
|
||||
}
|
||||
if (oh.isDirectNull())
|
||||
{
|
||||
@ -86,7 +86,7 @@ SparseOHArray::erase(size_t idx)
|
||||
{
|
||||
if (idx >= this->n_elements)
|
||||
{
|
||||
throw std::logic_error("bounds error erasing item from SparseOHArray");
|
||||
throw std::logic_error("bounds error erasing item from SparseOHArray");
|
||||
}
|
||||
decltype(this->elements) dest;
|
||||
for (auto const& iter: this->elements)
|
||||
|
124
libqpdf/bits.icc
124
libqpdf/bits.icc
@ -18,7 +18,7 @@
|
||||
#ifdef BITS_READ
|
||||
static unsigned long long
|
||||
read_bits(unsigned char const*& p, size_t& bit_offset,
|
||||
size_t& bits_available, size_t bits_wanted)
|
||||
size_t& bits_available, size_t bits_wanted)
|
||||
{
|
||||
// View p as a stream of bits:
|
||||
|
||||
@ -29,67 +29,67 @@ read_bits(unsigned char const*& p, size_t& bit_offset,
|
||||
|
||||
if (bits_wanted > bits_available)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
throw std::runtime_error(
|
||||
"overflow reading bit stream: wanted = " +
|
||||
QUtil::uint_to_string(bits_wanted) + "; available = " +
|
||||
QUtil::uint_to_string(bits_available));
|
||||
}
|
||||
if (bits_wanted > 32)
|
||||
{
|
||||
throw std::out_of_range("read_bits: too many bits requested");
|
||||
throw std::out_of_range("read_bits: too many bits requested");
|
||||
}
|
||||
|
||||
unsigned long result = 0;
|
||||
#ifdef BITS_TESTING
|
||||
if (bits_wanted == 0)
|
||||
{
|
||||
QTC::TC("libtests", "bits zero bits wanted");
|
||||
QTC::TC("libtests", "bits zero bits wanted");
|
||||
}
|
||||
#endif
|
||||
while (bits_wanted > 0)
|
||||
{
|
||||
// Grab bits from the first byte clearing anything before
|
||||
// bit_offset.
|
||||
unsigned char byte = static_cast<unsigned char>(
|
||||
// Grab bits from the first byte clearing anything before
|
||||
// bit_offset.
|
||||
unsigned char byte = static_cast<unsigned char>(
|
||||
*p & ((1U << (bit_offset + 1U)) - 1U));
|
||||
|
||||
// There are bit_offset + 1 bits available in the first byte.
|
||||
size_t to_copy = std::min(bits_wanted, bit_offset + 1);
|
||||
size_t leftover = (bit_offset + 1) - to_copy;
|
||||
// There are bit_offset + 1 bits available in the first byte.
|
||||
size_t to_copy = std::min(bits_wanted, bit_offset + 1);
|
||||
size_t leftover = (bit_offset + 1) - to_copy;
|
||||
|
||||
#ifdef BITS_TESTING
|
||||
QTC::TC("libtests", "bits bit_offset",
|
||||
((bit_offset == 0) ? 0 :
|
||||
(bit_offset == 7) ? 1 :
|
||||
2));
|
||||
QTC::TC("libtests", "bits leftover", (leftover > 0) ? 1 : 0);
|
||||
QTC::TC("libtests", "bits bit_offset",
|
||||
((bit_offset == 0) ? 0 :
|
||||
(bit_offset == 7) ? 1 :
|
||||
2));
|
||||
QTC::TC("libtests", "bits leftover", (leftover > 0) ? 1 : 0);
|
||||
#endif
|
||||
|
||||
// Right shift so that all the bits we want are right justified.
|
||||
byte = static_cast<unsigned char>(byte >> leftover);
|
||||
// Right shift so that all the bits we want are right justified.
|
||||
byte = static_cast<unsigned char>(byte >> leftover);
|
||||
|
||||
// Copy the bits into result
|
||||
result <<= to_copy;
|
||||
result |= byte;
|
||||
// Copy the bits into result
|
||||
result <<= to_copy;
|
||||
result |= byte;
|
||||
|
||||
// Update pointers
|
||||
if (leftover)
|
||||
{
|
||||
bit_offset = leftover - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit_offset = 7;
|
||||
++p;
|
||||
}
|
||||
bits_wanted -= to_copy;
|
||||
bits_available -= to_copy;
|
||||
// Update pointers
|
||||
if (leftover)
|
||||
{
|
||||
bit_offset = leftover - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bit_offset = 7;
|
||||
++p;
|
||||
}
|
||||
bits_wanted -= to_copy;
|
||||
bits_available -= to_copy;
|
||||
|
||||
#ifdef BITS_TESTING
|
||||
QTC::TC("libtests", "bits iterations",
|
||||
((bits_wanted > 8) ? 0 :
|
||||
(bits_wanted > 0) ? 1 :
|
||||
2));
|
||||
QTC::TC("libtests", "bits iterations",
|
||||
((bits_wanted > 8) ? 0 :
|
||||
(bits_wanted > 0) ? 1 :
|
||||
2));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -100,50 +100,50 @@ read_bits(unsigned char const*& p, size_t& bit_offset,
|
||||
#ifdef BITS_WRITE
|
||||
static void
|
||||
write_bits(unsigned char& ch, size_t& bit_offset,
|
||||
unsigned long long val, size_t bits, Pipeline* pipeline)
|
||||
unsigned long long val, size_t bits, Pipeline* pipeline)
|
||||
{
|
||||
if (bits > 32)
|
||||
{
|
||||
throw std::out_of_range("write_bits: too many bits requested");
|
||||
throw std::out_of_range("write_bits: too many bits requested");
|
||||
}
|
||||
|
||||
// bit_offset + 1 is the number of bits left in ch
|
||||
#ifdef BITS_TESTING
|
||||
if (bits == 0)
|
||||
{
|
||||
QTC::TC("libtests", "bits write zero bits");
|
||||
QTC::TC("libtests", "bits write zero bits");
|
||||
}
|
||||
#endif
|
||||
while (bits > 0)
|
||||
{
|
||||
size_t bits_to_write = std::min(bits, bit_offset + 1);
|
||||
unsigned char newval = static_cast<unsigned char>(
|
||||
(val >> (bits - bits_to_write)) & ((1U << bits_to_write) - 1));
|
||||
size_t bits_left_in_ch = bit_offset + 1 - bits_to_write;
|
||||
newval = static_cast<unsigned char>(newval << bits_left_in_ch);
|
||||
ch |= newval;
|
||||
if (bits_left_in_ch == 0)
|
||||
{
|
||||
size_t bits_to_write = std::min(bits, bit_offset + 1);
|
||||
unsigned char newval = static_cast<unsigned char>(
|
||||
(val >> (bits - bits_to_write)) & ((1U << bits_to_write) - 1));
|
||||
size_t bits_left_in_ch = bit_offset + 1 - bits_to_write;
|
||||
newval = static_cast<unsigned char>(newval << bits_left_in_ch);
|
||||
ch |= newval;
|
||||
if (bits_left_in_ch == 0)
|
||||
{
|
||||
#ifdef BITS_TESTING
|
||||
QTC::TC("libtests", "bits write pipeline");
|
||||
QTC::TC("libtests", "bits write pipeline");
|
||||
#endif
|
||||
pipeline->write(&ch, 1);
|
||||
bit_offset = 7;
|
||||
ch = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pipeline->write(&ch, 1);
|
||||
bit_offset = 7;
|
||||
ch = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef BITS_TESTING
|
||||
QTC::TC("libtests", "bits write leftover");
|
||||
QTC::TC("libtests", "bits write leftover");
|
||||
#endif
|
||||
bit_offset -= bits_to_write;
|
||||
}
|
||||
bits -= bits_to_write;
|
||||
bit_offset -= bits_to_write;
|
||||
}
|
||||
bits -= bits_to_write;
|
||||
#ifdef BITS_TESTING
|
||||
QTC::TC("libtests", "bits write iterations",
|
||||
((bits > 8) ? 0 :
|
||||
(bits > 0) ? 1 :
|
||||
2));
|
||||
QTC::TC("libtests", "bits write iterations",
|
||||
((bits > 8) ? 0 :
|
||||
(bits > 0) ? 1 :
|
||||
2));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ struct _qpdf_data
|
||||
std::string tmp_string;
|
||||
|
||||
// Parameters for functions we call
|
||||
char const* filename; // or description
|
||||
char const* filename; // or description
|
||||
char const* buffer;
|
||||
unsigned long long size;
|
||||
char const* password;
|
||||
@ -98,7 +98,7 @@ static void call_read(qpdf_data qpdf)
|
||||
static void call_read_memory(qpdf_data qpdf)
|
||||
{
|
||||
qpdf->qpdf->processMemoryFile(qpdf->filename, qpdf->buffer,
|
||||
QIntC::to_size(qpdf->size), qpdf->password);
|
||||
QIntC::to_size(qpdf->size), qpdf->password);
|
||||
}
|
||||
|
||||
// must set qpdf->filename
|
||||
@ -134,29 +134,29 @@ static QPDF_ERROR_CODE trap_errors(
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
try
|
||||
{
|
||||
fn(qpdf);
|
||||
fn(qpdf);
|
||||
}
|
||||
catch (QPDFExc& e)
|
||||
{
|
||||
qpdf->error = make_pointer_holder<QPDFExc>(e);
|
||||
status |= QPDF_ERRORS;
|
||||
qpdf->error = make_pointer_holder<QPDFExc>(e);
|
||||
status |= QPDF_ERRORS;
|
||||
}
|
||||
catch (std::runtime_error& e)
|
||||
{
|
||||
qpdf->error = make_pointer_holder<QPDFExc>(
|
||||
qpdf->error = make_pointer_holder<QPDFExc>(
|
||||
qpdf_e_system, "", "", 0, e.what());
|
||||
status |= QPDF_ERRORS;
|
||||
status |= QPDF_ERRORS;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
qpdf->error = make_pointer_holder<QPDFExc>(
|
||||
qpdf->error = make_pointer_holder<QPDFExc>(
|
||||
qpdf_e_internal, "", "", 0, e.what());
|
||||
status |= QPDF_ERRORS;
|
||||
status |= QPDF_ERRORS;
|
||||
}
|
||||
|
||||
if (qpdf_more_warnings(qpdf))
|
||||
{
|
||||
status |= QPDF_WARNINGS;
|
||||
status |= QPDF_WARNINGS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -202,19 +202,19 @@ QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf)
|
||||
|
||||
if (qpdf->warnings.empty())
|
||||
{
|
||||
std::vector<QPDFExc> w = qpdf->qpdf->getWarnings();
|
||||
if (! w.empty())
|
||||
{
|
||||
qpdf->warnings.assign(w.begin(), w.end());
|
||||
}
|
||||
std::vector<QPDFExc> w = qpdf->qpdf->getWarnings();
|
||||
if (! w.empty())
|
||||
{
|
||||
qpdf->warnings.assign(w.begin(), w.end());
|
||||
}
|
||||
}
|
||||
if (qpdf->warnings.empty())
|
||||
{
|
||||
return QPDF_FALSE;
|
||||
return QPDF_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return QPDF_TRUE;
|
||||
return QPDF_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,14 +228,14 @@ qpdf_error qpdf_get_error(qpdf_data qpdf)
|
||||
{
|
||||
if (qpdf->error.get())
|
||||
{
|
||||
qpdf->tmp_error.exc = qpdf->error;
|
||||
qpdf->error = 0;
|
||||
QTC::TC("qpdf", "qpdf-c qpdf_get_error returned error");
|
||||
return &qpdf->tmp_error;
|
||||
qpdf->tmp_error.exc = qpdf->error;
|
||||
qpdf->error = 0;
|
||||
QTC::TC("qpdf", "qpdf-c qpdf_get_error returned error");
|
||||
return &qpdf->tmp_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,15 +243,15 @@ qpdf_error qpdf_next_warning(qpdf_data qpdf)
|
||||
{
|
||||
if (qpdf_more_warnings(qpdf))
|
||||
{
|
||||
qpdf->tmp_error.exc = make_pointer_holder<QPDFExc>(
|
||||
qpdf->tmp_error.exc = make_pointer_holder<QPDFExc>(
|
||||
qpdf->warnings.front());
|
||||
qpdf->warnings.pop_front();
|
||||
QTC::TC("qpdf", "qpdf-c qpdf_next_warning returned warning");
|
||||
return &qpdf->tmp_error;
|
||||
qpdf->warnings.pop_front();
|
||||
QTC::TC("qpdf", "qpdf-c qpdf_next_warning returned warning");
|
||||
return &qpdf->tmp_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ char const* qpdf_get_error_full_text(qpdf_data qpdf, qpdf_error e)
|
||||
{
|
||||
if (e == 0)
|
||||
{
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
return e->exc->what();
|
||||
}
|
||||
@ -268,7 +268,7 @@ enum qpdf_error_code_e qpdf_get_error_code(qpdf_data qpdf, qpdf_error e)
|
||||
{
|
||||
if (e == 0)
|
||||
{
|
||||
return qpdf_e_success;
|
||||
return qpdf_e_success;
|
||||
}
|
||||
return e->exc->getErrorCode();
|
||||
}
|
||||
@ -277,7 +277,7 @@ char const* qpdf_get_error_filename(qpdf_data qpdf, qpdf_error e)
|
||||
{
|
||||
if (e == 0)
|
||||
{
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
return e->exc->getFilename().c_str();
|
||||
}
|
||||
@ -286,7 +286,7 @@ unsigned long long qpdf_get_error_file_position(qpdf_data qpdf, qpdf_error e)
|
||||
{
|
||||
if (e == 0)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
return QIntC::to_ulonglong(e->exc->getFilePosition());
|
||||
}
|
||||
@ -295,7 +295,7 @@ char const* qpdf_get_error_message_detail(qpdf_data qpdf, qpdf_error e)
|
||||
{
|
||||
if (e == 0)
|
||||
{
|
||||
return "";
|
||||
return "";
|
||||
}
|
||||
return e->exc->getMessageDetail().c_str();
|
||||
}
|
||||
@ -326,7 +326,7 @@ void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value)
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
|
||||
char const* password)
|
||||
char const* password)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
qpdf->filename = filename;
|
||||
@ -345,10 +345,10 @@ QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
|
||||
}
|
||||
|
||||
QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf,
|
||||
char const* description,
|
||||
char const* buffer,
|
||||
unsigned long long size,
|
||||
char const* password)
|
||||
char const* description,
|
||||
char const* buffer,
|
||||
unsigned long long size,
|
||||
char const* password)
|
||||
{
|
||||
QPDF_ERROR_CODE status = QPDF_SUCCESS;
|
||||
qpdf->filename = description;
|
||||
@ -394,16 +394,16 @@ char const* qpdf_get_info_key(qpdf_data qpdf, char const* key)
|
||||
QPDFObjectHandle trailer = qpdf->qpdf->getTrailer();
|
||||
if (trailer.hasKey("/Info"))
|
||||
{
|
||||
QPDFObjectHandle info = trailer.getKey("/Info");
|
||||
if (info.hasKey(key))
|
||||
{
|
||||
QPDFObjectHandle value = info.getKey(key);
|
||||
if (value.isString())
|
||||
{
|
||||
qpdf->tmp_string = value.getStringValue();
|
||||
result = qpdf->tmp_string.c_str();
|
||||
}
|
||||
}
|
||||
QPDFObjectHandle info = trailer.getKey("/Info");
|
||||
if (info.hasKey(key))
|
||||
{
|
||||
QPDFObjectHandle value = info.getKey(key);
|
||||
if (value.isString())
|
||||
{
|
||||
qpdf->tmp_string = value.getStringValue();
|
||||
result = qpdf->tmp_string.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
QTC::TC("qpdf", "qpdf-c get_info_key", (result == 0 ? 0 : 1));
|
||||
return result;
|
||||
@ -413,31 +413,31 @@ void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value)
|
||||
{
|
||||
if ((key == 0) || (std::strlen(key) == 0) || (key[0] != '/'))
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
QPDFObjectHandle value_object;
|
||||
if (value)
|
||||
{
|
||||
QTC::TC("qpdf", "qpdf-c set_info_key to value");
|
||||
value_object = QPDFObjectHandle::newString(value);
|
||||
QTC::TC("qpdf", "qpdf-c set_info_key to value");
|
||||
value_object = QPDFObjectHandle::newString(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "qpdf-c set_info_key to null");
|
||||
value_object = QPDFObjectHandle::newNull();
|
||||
QTC::TC("qpdf", "qpdf-c set_info_key to null");
|
||||
value_object = QPDFObjectHandle::newNull();
|
||||
}
|
||||
|
||||
QPDFObjectHandle trailer = qpdf->qpdf->getTrailer();
|
||||
if (! trailer.hasKey("/Info"))
|
||||
{
|
||||
QTC::TC("qpdf", "qpdf-c add info to trailer");
|
||||
trailer.replaceKey(
|
||||
"/Info",
|
||||
qpdf->qpdf->makeIndirectObject(QPDFObjectHandle::newDictionary()));
|
||||
QTC::TC("qpdf", "qpdf-c add info to trailer");
|
||||
trailer.replaceKey(
|
||||
"/Info",
|
||||
qpdf->qpdf->makeIndirectObject(QPDFObjectHandle::newDictionary()));
|
||||
}
|
||||
else
|
||||
{
|
||||
QTC::TC("qpdf", "qpdf-c set-info-key use existing info");
|
||||
QTC::TC("qpdf", "qpdf-c set-info-key use existing info");
|
||||
}
|
||||
|
||||
QPDFObjectHandle info = trailer.getKey("/Info");
|
||||
@ -514,14 +514,14 @@ static void qpdf_init_write_internal(qpdf_data qpdf)
|
||||
{
|
||||
if (qpdf->qpdf_writer.get())
|
||||
{
|
||||
QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times");
|
||||
qpdf->qpdf_writer = 0;
|
||||
if (qpdf->output_buffer.get())
|
||||
{
|
||||
qpdf->output_buffer = 0;
|
||||
qpdf->write_memory = false;
|
||||
qpdf->filename = 0;
|
||||
}
|
||||
QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times");
|
||||
qpdf->qpdf_writer = 0;
|
||||
if (qpdf->output_buffer.get())
|
||||
{
|
||||
qpdf->output_buffer = 0;
|
||||
qpdf->write_memory = false;
|
||||
qpdf->filename = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,7 +547,7 @@ static void qpdf_get_buffer_internal(qpdf_data qpdf)
|
||||
{
|
||||
if (qpdf->write_memory && (qpdf->output_buffer == 0))
|
||||
{
|
||||
qpdf->output_buffer = qpdf->qpdf_writer->getBufferSharedPointer();
|
||||
qpdf->output_buffer = qpdf->qpdf_writer->getBufferSharedPointer();
|
||||
}
|
||||
}
|
||||
|
||||
@ -557,7 +557,7 @@ size_t qpdf_get_buffer_length(qpdf_data qpdf)
|
||||
size_t result = 0;
|
||||
if (qpdf->output_buffer.get())
|
||||
{
|
||||
result = qpdf->output_buffer->getSize();
|
||||
result = qpdf->output_buffer->getSize();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -568,7 +568,7 @@ unsigned char const* qpdf_get_buffer(qpdf_data qpdf)
|
||||
qpdf_get_buffer_internal(qpdf);
|
||||
if (qpdf->output_buffer.get())
|
||||
{
|
||||
result = qpdf->output_buffer->getBuffer();
|
||||
result = qpdf->output_buffer->getBuffer();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -659,8 +659,8 @@ void qpdf_set_r2_encryption_parameters(
|
||||
{
|
||||
QTC::TC("qpdf", "qpdf-c called qpdf_set_r2_encryption_parameters");
|
||||
qpdf->qpdf_writer->setR2EncryptionParameters(
|
||||
user_password, owner_password,
|
||||
allow_print != QPDF_FALSE, allow_modify != QPDF_FALSE,
|
||||
user_password, owner_password,
|
||||
allow_print != QPDF_FALSE, allow_modify != QPDF_FALSE,
|
||||
allow_extract != QPDF_FALSE, allow_annotate != QPDF_FALSE);
|
||||
}
|
||||
|
||||
@ -743,8 +743,8 @@ void qpdf_set_r3_encryption_parameters(
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
qpdf->qpdf_writer->setR3EncryptionParameters(
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
print, modify);
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
@ -765,10 +765,10 @@ void qpdf_set_r4_encryption_parameters(
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
qpdf->qpdf_writer->setR4EncryptionParameters(
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
print, modify,
|
||||
encrypt_metadata != QPDF_FALSE, use_aes != QPDF_FALSE);
|
||||
encrypt_metadata != QPDF_FALSE, use_aes != QPDF_FALSE);
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
@ -788,10 +788,10 @@ void qpdf_set_r5_encryption_parameters(
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
qpdf->qpdf_writer->setR5EncryptionParameters(
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
print, modify,
|
||||
encrypt_metadata != QPDF_FALSE);
|
||||
encrypt_metadata != QPDF_FALSE);
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
@ -811,8 +811,8 @@ void qpdf_set_r6_encryption_parameters(
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
qpdf->qpdf_writer->setR6EncryptionParameters(
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
user_password, owner_password,
|
||||
allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
|
||||
print, modify, encrypt_metadata != QPDF_FALSE);
|
||||
#if (defined(__GNUC__) || defined(__clang__))
|
||||
# pragma GCC diagnostic pop
|
||||
|
@ -51,13 +51,13 @@ class MD5
|
||||
static std::string getDataChecksum(char const* buf, size_t len);
|
||||
QPDF_DLL
|
||||
static std::string getFileChecksum(char const* filename,
|
||||
qpdf_offset_t up_to_offset = -1);
|
||||
qpdf_offset_t up_to_offset = -1);
|
||||
QPDF_DLL
|
||||
static bool checkDataChecksum(char const* const checksum,
|
||||
char const* buf, size_t len);
|
||||
char const* buf, size_t len);
|
||||
QPDF_DLL
|
||||
static bool checkFileChecksum(char const* const checksum,
|
||||
char const* filename,
|
||||
char const* filename,
|
||||
qpdf_offset_t up_to_offset = -1);
|
||||
|
||||
private:
|
||||
|
@ -21,9 +21,9 @@ class MD5_native
|
||||
static void encode(unsigned char *, uint32_t *, size_t);
|
||||
static void decode(uint32_t *, unsigned char *, size_t);
|
||||
|
||||
uint32_t state[4]; // state (ABCD)
|
||||
uint32_t count[2]; // number of bits, modulo 2^64 (lsb first)
|
||||
unsigned char buffer[64]; // input buffer
|
||||
uint32_t state[4]; // state (ABCD)
|
||||
uint32_t count[2]; // number of bits, modulo 2^64 (lsb first)
|
||||
unsigned char buffer[64]; // input buffer
|
||||
|
||||
bool finalized;
|
||||
Digest digest_val;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user