mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 02:49:00 +00:00
Programmatically apply new formatting to code
Run this: for i in **/*.cc **/*.c **/*.h **/*.hh; do clang-format < $i >| $i.new && mv $i.new $i done
This commit is contained in:
parent
f20fa61eb4
commit
12f1eb15ca
@ -1,11 +1,11 @@
|
|||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QPDFWriter.hh>
|
|
||||||
#include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
|
#include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFFileSpecObjectHelper.hh>
|
#include <qpdf/QPDFFileSpecObjectHelper.hh>
|
||||||
|
#include <qpdf/QPDFWriter.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
//
|
//
|
||||||
// This example attaches a file to an input file, adds a page to the
|
// This example attaches a file to an input file, adds a page to the
|
||||||
@ -17,9 +17,11 @@
|
|||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
static void usage(std::string const& msg)
|
static void
|
||||||
|
usage(std::string const& msg)
|
||||||
{
|
{
|
||||||
std::cerr << msg << std::endl << std::endl
|
std::cerr << msg << std::endl
|
||||||
|
<< std::endl
|
||||||
<< "Usage: " << whoami << " options" << std::endl
|
<< "Usage: " << whoami << " options" << std::endl
|
||||||
<< "Options:" << std::endl
|
<< "Options:" << std::endl
|
||||||
<< " --infile infile.pdf" << std::endl
|
<< " --infile infile.pdf" << std::endl
|
||||||
@ -30,33 +32,36 @@ static void usage(std::string const& msg)
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process(char const* infilename, char const* password,
|
static void
|
||||||
char const* attachment, char const* mimetype,
|
process(
|
||||||
char const* outfilename)
|
char const* infilename,
|
||||||
|
char const* password,
|
||||||
|
char const* attachment,
|
||||||
|
char const* mimetype,
|
||||||
|
char const* outfilename)
|
||||||
{
|
{
|
||||||
QPDF q;
|
QPDF q;
|
||||||
q.processFile(infilename, password);
|
q.processFile(infilename, password);
|
||||||
|
|
||||||
// Create an indirect object for the built-in Helvetica font. This
|
// Create an indirect object for the built-in Helvetica font. This
|
||||||
// uses the qpdf literal syntax introduced in qpdf 10.6.
|
// uses the qpdf literal syntax introduced in qpdf 10.6.
|
||||||
auto f1 = q.makeIndirectObject(
|
auto f1 = q.makeIndirectObject("<<"
|
||||||
"<<"
|
" /Type /Font"
|
||||||
" /Type /Font"
|
" /Subtype /Type1"
|
||||||
" /Subtype /Type1"
|
" /Name /F1"
|
||||||
" /Name /F1"
|
" /BaseFont /Helvetica"
|
||||||
" /BaseFont /Helvetica"
|
" /Encoding /WinAnsiEncoding"
|
||||||
" /Encoding /WinAnsiEncoding"
|
">>"_qpdf);
|
||||||
">>"_qpdf);
|
|
||||||
|
|
||||||
// Create a resources dictionary with fonts. This uses the new
|
// Create a resources dictionary with fonts. This uses the new
|
||||||
// parse introduced in qpdf 10.2 that takes a QPDF* and allows
|
// parse introduced in qpdf 10.2 that takes a QPDF* and allows
|
||||||
// indirect object references.
|
// indirect object references.
|
||||||
auto resources = q.makeIndirectObject(
|
auto resources = q.makeIndirectObject(QPDFObjectHandle::parse(
|
||||||
QPDFObjectHandle::parse(
|
&q,
|
||||||
&q,
|
"<<"
|
||||||
"<<"
|
" /Font <<"
|
||||||
" /Font <<"
|
" /F1 " +
|
||||||
" /F1 " + f1.unparse() +
|
f1.unparse() +
|
||||||
" >>"
|
" >>"
|
||||||
">>"));
|
">>"));
|
||||||
|
|
||||||
@ -66,8 +71,7 @@ static void process(char const* infilename, char const* password,
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
auto fs = QPDFFileSpecObjectHelper::createFileSpec(q, key, attachment);
|
auto fs = QPDFFileSpecObjectHelper::createFileSpec(q, key, attachment);
|
||||||
|
|
||||||
if (mimetype)
|
if (mimetype) {
|
||||||
{
|
|
||||||
// Get an embedded file stream and set mimetype
|
// Get an embedded file stream and set mimetype
|
||||||
auto ef = QPDFEFStreamObjectHelper(fs.getEmbeddedFileStream());
|
auto ef = QPDFEFStreamObjectHelper(fs.getEmbeddedFileStream());
|
||||||
ef.setSubtype(mimetype);
|
ef.setSubtype(mimetype);
|
||||||
@ -102,17 +106,16 @@ static void process(char const* infilename, char const* password,
|
|||||||
apdict.replaceKey("/Type", "/XObject"_qpdf);
|
apdict.replaceKey("/Type", "/XObject"_qpdf);
|
||||||
apdict.replaceKey("/Subtype", "/Form"_qpdf);
|
apdict.replaceKey("/Subtype", "/Form"_qpdf);
|
||||||
apdict.replaceKey("/BBox", "[ 0 0 20 20 ]"_qpdf);
|
apdict.replaceKey("/BBox", "[ 0 0 20 20 ]"_qpdf);
|
||||||
auto annot = q.makeIndirectObject(
|
auto annot = q.makeIndirectObject(QPDFObjectHandle::parse(
|
||||||
QPDFObjectHandle::parse(
|
&q,
|
||||||
&q,
|
"<<"
|
||||||
"<<"
|
" /AP <<"
|
||||||
" /AP <<"
|
" /N " +
|
||||||
" /N " + ap.unparse() +
|
ap.unparse() +
|
||||||
" >>"
|
" >>"
|
||||||
" /Contents "
|
" /Contents " +
|
||||||
+ QPDFObjectHandle::newUnicodeString(attachment).unparse() +
|
QPDFObjectHandle::newUnicodeString(attachment).unparse() +
|
||||||
" /FS " + fs.getObjectHandle().unparse() +
|
" /FS " + fs.getObjectHandle().unparse() + " /NM " +
|
||||||
" /NM " +
|
|
||||||
QPDFObjectHandle::newUnicodeString(attachment).unparse() +
|
QPDFObjectHandle::newUnicodeString(attachment).unparse() +
|
||||||
" /Rect [ 72 700 92 720 ]"
|
" /Rect [ 72 700 92 720 ]"
|
||||||
" /Subtype /FileAttachment"
|
" /Subtype /FileAttachment"
|
||||||
@ -134,12 +137,16 @@ static void process(char const* infilename, char const* password,
|
|||||||
auto page = QPDFObjectHandle::parse(
|
auto page = QPDFObjectHandle::parse(
|
||||||
&q,
|
&q,
|
||||||
"<<"
|
"<<"
|
||||||
" /Annots [ " + annot.unparse() + " ]"
|
" /Annots [ " +
|
||||||
" /Contents " + contents.unparse() +
|
annot.unparse() +
|
||||||
" /MediaBox [0 0 612 792]"
|
" ]"
|
||||||
" /Resources " + resources.unparse() +
|
" /Contents " +
|
||||||
" /Type /Page"
|
contents.unparse() +
|
||||||
">>");
|
" /MediaBox [0 0 612 792]"
|
||||||
|
" /Resources " +
|
||||||
|
resources.unparse() +
|
||||||
|
" /Type /Page"
|
||||||
|
">>");
|
||||||
|
|
||||||
// Add the page.
|
// Add the page.
|
||||||
q.addPage(page, true);
|
q.addPage(page, true);
|
||||||
@ -151,7 +158,8 @@ static void process(char const* infilename, char const* password,
|
|||||||
w.write();
|
w.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
@ -162,64 +170,46 @@ int main(int argc, char* argv[])
|
|||||||
char const* mimetype = 0;
|
char const* mimetype = 0;
|
||||||
|
|
||||||
auto check_arg = [](char const* arg, std::string const& msg) {
|
auto check_arg = [](char const* arg, std::string const& msg) {
|
||||||
if (arg == nullptr)
|
if (arg == nullptr) {
|
||||||
{
|
|
||||||
usage(msg);
|
usage(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i) {
|
||||||
{
|
|
||||||
char* arg = argv[i];
|
char* arg = argv[i];
|
||||||
char* next = argv[i+1];
|
char* next = argv[i + 1];
|
||||||
if (strcmp(arg, "--infile") == 0)
|
if (strcmp(arg, "--infile") == 0) {
|
||||||
{
|
|
||||||
check_arg(next, "--infile takes an argument");
|
check_arg(next, "--infile takes an argument");
|
||||||
infilename = next;
|
infilename = next;
|
||||||
++i;
|
++i;
|
||||||
}
|
} else if (strcmp(arg, "--password") == 0) {
|
||||||
else if (strcmp(arg, "--password") == 0)
|
|
||||||
{
|
|
||||||
check_arg(next, "--password takes an argument");
|
check_arg(next, "--password takes an argument");
|
||||||
password = next;
|
password = next;
|
||||||
++i;
|
++i;
|
||||||
}
|
} else if (strcmp(arg, "--attachment") == 0) {
|
||||||
else if (strcmp(arg, "--attachment") == 0)
|
|
||||||
{
|
|
||||||
check_arg(next, "--attachment takes an argument");
|
check_arg(next, "--attachment takes an argument");
|
||||||
attachment = next;
|
attachment = next;
|
||||||
++i;
|
++i;
|
||||||
}
|
} else if (strcmp(arg, "--outfile") == 0) {
|
||||||
else if (strcmp(arg, "--outfile") == 0)
|
|
||||||
{
|
|
||||||
check_arg(next, "--outfile takes an argument");
|
check_arg(next, "--outfile takes an argument");
|
||||||
outfilename = next;
|
outfilename = next;
|
||||||
++i;
|
++i;
|
||||||
}
|
} else if (strcmp(arg, "--mimetype") == 0) {
|
||||||
else if (strcmp(arg, "--mimetype") == 0)
|
|
||||||
{
|
|
||||||
check_arg(next, "--mimetype takes an argument");
|
check_arg(next, "--mimetype takes an argument");
|
||||||
mimetype = next;
|
mimetype = next;
|
||||||
++i;
|
++i;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
usage("unknown argument " + std::string(arg));
|
usage("unknown argument " + std::string(arg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! (infilename && attachment && outfilename))
|
if (!(infilename && attachment && outfilename)) {
|
||||||
{
|
|
||||||
usage("required arguments were not provided");
|
usage("required arguments were not provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
process(infilename, password, attachment, mimetype, outfilename);
|
process(infilename, password, attachment, mimetype, outfilename);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
std::cerr << whoami << " exception: " << e.what() << std::endl;
|
||||||
{
|
|
||||||
std::cerr << whoami << " exception: "
|
|
||||||
<< e.what() << std::endl;
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <qpdf/QPDF.hh>
|
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
|
||||||
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
|
#include <qpdf/QPDF.hh>
|
||||||
|
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
||||||
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QTC.hh>
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
// This program demonstrates extraction of bookmarks using the qpdf
|
// This program demonstrates extraction of bookmarks using the qpdf
|
||||||
// outlines API. Note that all the information shown by this program
|
// outlines API. Note that all the information shown by this program
|
||||||
@ -20,67 +20,62 @@ static bool show_open = false;
|
|||||||
static bool show_targets = false;
|
static bool show_targets = false;
|
||||||
static std::map<QPDFObjGen, int> page_map;
|
static std::map<QPDFObjGen, int> page_map;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " [options] file.pdf [password]"
|
std::cerr
|
||||||
<< std::endl
|
<< "Usage: " << whoami << " [options] file.pdf [password]" << std::endl
|
||||||
<< "Options:" << std::endl
|
<< "Options:" << std::endl
|
||||||
<< " --numbers give bookmarks outline-style numbers"
|
<< " --numbers give bookmarks outline-style numbers"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< " --lines draw lines to show bookmark hierarchy"
|
<< " --lines draw lines to show bookmark hierarchy"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< " --show-open indicate whether a bookmark is initially open"
|
<< " --show-open indicate whether a bookmark is initially open"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
<< " --show-targets show target if possible"
|
<< " --show-targets show target if possible" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_lines(std::vector<int>& numbers)
|
void
|
||||||
|
print_lines(std::vector<int>& numbers)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < numbers.size() - 1; ++i)
|
for (unsigned int i = 0; i < numbers.size() - 1; ++i) {
|
||||||
{
|
if (numbers.at(i)) {
|
||||||
if (numbers.at(i))
|
|
||||||
{
|
|
||||||
std::cout << "| ";
|
std::cout << "| ";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << " ";
|
std::cout << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_page_map(QPDF& qpdf)
|
void
|
||||||
|
generate_page_map(QPDF& qpdf)
|
||||||
{
|
{
|
||||||
QPDFPageDocumentHelper dh(qpdf);
|
QPDFPageDocumentHelper dh(qpdf);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (auto const& page : dh.getAllPages())
|
for (auto const& page : dh.getAllPages()) {
|
||||||
{
|
|
||||||
page_map[page.getObjectHandle().getObjGen()] = ++n;
|
page_map[page.getObjectHandle().getObjGen()] = ++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_bookmark_details(QPDFOutlineObjectHelper outline,
|
void
|
||||||
std::vector<int> numbers)
|
show_bookmark_details(QPDFOutlineObjectHelper outline, std::vector<int> numbers)
|
||||||
{
|
{
|
||||||
// No default so gcc will warn on missing tag
|
// No default so gcc will warn on missing tag
|
||||||
switch (style)
|
switch (style) {
|
||||||
{
|
case st_none:
|
||||||
case st_none:
|
|
||||||
QTC::TC("examples", "pdf-bookmarks none");
|
QTC::TC("examples", "pdf-bookmarks none");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case st_numbers:
|
case st_numbers:
|
||||||
QTC::TC("examples", "pdf-bookmarks numbers");
|
QTC::TC("examples", "pdf-bookmarks numbers");
|
||||||
for (auto const& number : numbers)
|
for (auto const& number : numbers) {
|
||||||
{
|
|
||||||
std::cout << number << ".";
|
std::cout << number << ".";
|
||||||
}
|
}
|
||||||
std::cout << " ";
|
std::cout << " ";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case st_lines:
|
case st_lines:
|
||||||
QTC::TC("examples", "pdf-bookmarks lines");
|
QTC::TC("examples", "pdf-bookmarks lines");
|
||||||
print_lines(numbers);
|
print_lines(numbers);
|
||||||
std::cout << "|" << std::endl;
|
std::cout << "|" << std::endl;
|
||||||
@ -89,42 +84,32 @@ void show_bookmark_details(QPDFOutlineObjectHelper outline,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_open)
|
if (show_open) {
|
||||||
{
|
|
||||||
int count = outline.getCount();
|
int count = outline.getCount();
|
||||||
if (count)
|
if (count) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-bookmarks has count");
|
QTC::TC("examples", "pdf-bookmarks has count");
|
||||||
if (count > 0)
|
if (count > 0) {
|
||||||
{
|
|
||||||
// hierarchy is open at this point
|
// hierarchy is open at this point
|
||||||
QTC::TC("examples", "pdf-bookmarks open");
|
QTC::TC("examples", "pdf-bookmarks open");
|
||||||
std::cout << "(v) ";
|
std::cout << "(v) ";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-bookmarks closed");
|
QTC::TC("examples", "pdf-bookmarks closed");
|
||||||
std::cout << "(>) ";
|
std::cout << "(>) ";
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-bookmarks no count");
|
QTC::TC("examples", "pdf-bookmarks no count");
|
||||||
std::cout << "( ) ";
|
std::cout << "( ) ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_targets)
|
if (show_targets) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-bookmarks targets");
|
QTC::TC("examples", "pdf-bookmarks targets");
|
||||||
std::string target = "unknown";
|
std::string target = "unknown";
|
||||||
QPDFObjectHandle dest_page = outline.getDestPage();
|
QPDFObjectHandle dest_page = outline.getDestPage();
|
||||||
if (! dest_page.isNull())
|
if (!dest_page.isNull()) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-bookmarks dest");
|
QTC::TC("examples", "pdf-bookmarks dest");
|
||||||
QPDFObjGen og = dest_page.getObjGen();
|
QPDFObjGen og = dest_page.getObjGen();
|
||||||
if (page_map.count(og))
|
if (page_map.count(og)) {
|
||||||
{
|
|
||||||
target = QUtil::int_to_string(page_map[og]);
|
target = QUtil::int_to_string(page_map[og]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,8 +119,9 @@ void show_bookmark_details(QPDFOutlineObjectHelper outline,
|
|||||||
std::cout << outline.getTitle() << std::endl;
|
std::cout << outline.getTitle() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines,
|
void
|
||||||
std::vector<int>& numbers)
|
extract_bookmarks(
|
||||||
|
std::vector<QPDFOutlineObjectHelper> outlines, std::vector<int>& numbers)
|
||||||
{
|
{
|
||||||
// For style == st_numbers, numbers.at(n) contains the numerical
|
// For style == st_numbers, numbers.at(n) contains the numerical
|
||||||
// label for the outline, so we count up from 1.
|
// label for the outline, so we count up from 1.
|
||||||
@ -144,8 +130,7 @@ void extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines,
|
|||||||
// is, so we count up to zero.
|
// is, so we count up to zero.
|
||||||
numbers.push_back(
|
numbers.push_back(
|
||||||
(style == st_lines) ? -QIntC::to_int(outlines.size()) : 0);
|
(style == st_lines) ? -QIntC::to_int(outlines.size()) : 0);
|
||||||
for (auto& outline : outlines)
|
for (auto& outline : outlines) {
|
||||||
{
|
|
||||||
++(numbers.back());
|
++(numbers.back());
|
||||||
show_bookmark_details(outline, numbers);
|
show_bookmark_details(outline, numbers);
|
||||||
extract_bookmarks(outline.getKids(), numbers);
|
extract_bookmarks(outline.getKids(), numbers);
|
||||||
@ -153,87 +138,64 @@ void extract_bookmarks(std::vector<QPDFOutlineObjectHelper> outlines,
|
|||||||
numbers.pop_back();
|
numbers.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
|
if ((argc == 2) && (strcmp(argv[1], "--version") == 0)) {
|
||||||
{
|
|
||||||
std::cout << whoami << " version 1.5" << std::endl;
|
std::cout << whoami << " version 1.5" << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int arg;
|
int arg;
|
||||||
for (arg = 1; arg < argc; ++arg)
|
for (arg = 1; arg < argc; ++arg) {
|
||||||
{
|
if (argv[arg][0] == '-') {
|
||||||
if (argv[arg][0] == '-')
|
if (strcmp(argv[arg], "--numbers") == 0) {
|
||||||
{
|
|
||||||
if (strcmp(argv[arg], "--numbers") == 0)
|
|
||||||
{
|
|
||||||
style = st_numbers;
|
style = st_numbers;
|
||||||
}
|
} else if (strcmp(argv[arg], "--lines") == 0) {
|
||||||
else if (strcmp(argv[arg], "--lines") == 0)
|
|
||||||
{
|
|
||||||
style = st_lines;
|
style = st_lines;
|
||||||
}
|
} else if (strcmp(argv[arg], "--show-open") == 0) {
|
||||||
else if (strcmp(argv[arg], "--show-open") == 0)
|
|
||||||
{
|
|
||||||
show_open = true;
|
show_open = true;
|
||||||
}
|
} else if (strcmp(argv[arg], "--show-targets") == 0) {
|
||||||
else if (strcmp(argv[arg], "--show-targets") == 0)
|
|
||||||
{
|
|
||||||
show_targets = true;
|
show_targets = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg >= argc)
|
if (arg >= argc) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* filename = argv[arg++];
|
char const* filename = argv[arg++];
|
||||||
char const* password = "";
|
char const* password = "";
|
||||||
|
|
||||||
if (arg < argc)
|
if (arg < argc) {
|
||||||
{
|
|
||||||
password = argv[arg++];
|
password = argv[arg++];
|
||||||
}
|
}
|
||||||
if (arg != argc)
|
if (arg != argc) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF qpdf;
|
QPDF qpdf;
|
||||||
qpdf.processFile(filename, password);
|
qpdf.processFile(filename, password);
|
||||||
|
|
||||||
QPDFOutlineDocumentHelper odh(qpdf);
|
QPDFOutlineDocumentHelper odh(qpdf);
|
||||||
if (odh.hasOutlines())
|
if (odh.hasOutlines()) {
|
||||||
{
|
|
||||||
std::vector<int> numbers;
|
std::vector<int> numbers;
|
||||||
if (show_targets)
|
if (show_targets) {
|
||||||
{
|
|
||||||
generate_page_map(qpdf);
|
generate_page_map(qpdf);
|
||||||
}
|
}
|
||||||
extract_bookmarks(odh.getTopLevelOutlines(), numbers);
|
extract_bookmarks(odh.getTopLevelOutlines(), numbers);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << filename << " has no bookmarks" << std::endl;
|
std::cout << filename << " has no bookmarks" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << " processing file " << filename << ": "
|
std::cerr << whoami << " processing file " << filename << ": "
|
||||||
<< e.what() << std::endl;
|
<< e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
static void usage()
|
static void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s infile infile-password outfile\n", whoami);
|
fprintf(stderr, "Usage: %s infile infile-password outfile\n", whoami);
|
||||||
exit(2);
|
exit(2);
|
||||||
@ -33,12 +34,9 @@ modify_file(qpdf_data qpdf)
|
|||||||
/* 0 is never a valid qpdf_oh */
|
/* 0 is never a valid qpdf_oh */
|
||||||
qpdf_oh pagemode = 0;
|
qpdf_oh pagemode = 0;
|
||||||
if (qpdf_oh_is_dictionary(
|
if (qpdf_oh_is_dictionary(
|
||||||
qpdf, qpdf_oh_get_key(qpdf, root, "/PageLabels")))
|
qpdf, qpdf_oh_get_key(qpdf, root, "/PageLabels"))) {
|
||||||
{
|
|
||||||
pagemode = qpdf_oh_new_name(qpdf, "/UseOutlines");
|
pagemode = qpdf_oh_new_name(qpdf, "/UseOutlines");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
pagemode = qpdf_oh_new_null(qpdf);
|
pagemode = qpdf_oh_new_null(qpdf);
|
||||||
}
|
}
|
||||||
qpdf_oh_replace_or_remove_key(qpdf, root, "/PageMode", pagemode);
|
qpdf_oh_replace_or_remove_key(qpdf, root, "/PageMode", pagemode);
|
||||||
@ -46,7 +44,8 @@ modify_file(qpdf_data qpdf)
|
|||||||
return QPDF_TRUE;
|
return QPDF_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
char* infile = NULL;
|
char* infile = NULL;
|
||||||
char* password = NULL;
|
char* password = NULL;
|
||||||
@ -56,21 +55,15 @@ int main(int argc, char* argv[])
|
|||||||
int errors = 0;
|
int errors = 0;
|
||||||
char* p = 0;
|
char* p = 0;
|
||||||
|
|
||||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
if ((p = strrchr(argv[0], '/')) != NULL) {
|
||||||
{
|
|
||||||
whoami = p + 1;
|
whoami = p + 1;
|
||||||
}
|
} else if ((p = strrchr(argv[0], '\\')) != NULL) {
|
||||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
|
||||||
{
|
|
||||||
whoami = p + 1;
|
whoami = p + 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
whoami = argv[0];
|
whoami = argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 4)
|
if (argc != 4) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,33 +73,29 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
||||||
modify_file(qpdf) &&
|
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
|
/* Use static ID for testing only. For production, a
|
||||||
* non-static ID is used. See also
|
* non-static ID is used. See also
|
||||||
* qpdf_set_deterministic_ID. */
|
* qpdf_set_deterministic_ID. */
|
||||||
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
qpdf_set_static_ID(qpdf, QPDF_TRUE); /* for testing only */
|
||||||
qpdf_write(qpdf);
|
qpdf_write(qpdf);
|
||||||
}
|
}
|
||||||
while (qpdf_more_warnings(qpdf))
|
while (qpdf_more_warnings(qpdf)) {
|
||||||
{
|
|
||||||
warnings = 1;
|
warnings = 1;
|
||||||
printf("warning: %s\n",
|
printf(
|
||||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
"warning: %s\n",
|
||||||
|
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||||
}
|
}
|
||||||
if (qpdf_has_error(qpdf))
|
if (qpdf_has_error(qpdf)) {
|
||||||
{
|
|
||||||
errors = 1;
|
errors = 1;
|
||||||
printf("error: %s\n",
|
printf(
|
||||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
"error: %s\n",
|
||||||
|
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||||
}
|
}
|
||||||
qpdf_cleanup(&qpdf);
|
qpdf_cleanup(&qpdf);
|
||||||
if (errors)
|
if (errors) {
|
||||||
{
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
} else if (warnings) {
|
||||||
else if (warnings)
|
|
||||||
{
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,23 +5,23 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <qpdf/Pl_StdioFile.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/Pl_StdioFile.hh>
|
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile" << std::endl
|
std::cerr << "Usage: " << whoami << " infile" << std::endl
|
||||||
<< "Applies token filters to infile"
|
<< "Applies token filters to infile" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +47,7 @@ void
|
|||||||
StringCounter::handleToken(QPDFTokenizer::Token const& token)
|
StringCounter::handleToken(QPDFTokenizer::Token const& token)
|
||||||
{
|
{
|
||||||
// Count string tokens
|
// Count string tokens
|
||||||
if (token.getType() == QPDFTokenizer::tt_string)
|
if (token.getType() == QPDFTokenizer::tt_string) {
|
||||||
{
|
|
||||||
++this->count;
|
++this->count;
|
||||||
}
|
}
|
||||||
// Preserve input verbatim by passing each token to any specified
|
// Preserve input verbatim by passing each token to any specified
|
||||||
@ -71,36 +70,31 @@ StringCounter::getCount() const
|
|||||||
return this->count;
|
return this->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
char const* infilename = argv[1];
|
char const* infilename = argv[1];
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
pdf.processFile(infilename);
|
pdf.processFile(infilename);
|
||||||
int pageno = 0;
|
int pageno = 0;
|
||||||
for (auto& page : QPDFPageDocumentHelper(pdf).getAllPages())
|
for (auto& page : QPDFPageDocumentHelper(pdf).getAllPages()) {
|
||||||
{
|
|
||||||
++pageno;
|
++pageno;
|
||||||
// Pass the contents of a page through our string counter.
|
// Pass the contents of a page through our string counter.
|
||||||
// If it's an even page, capture the output. This
|
// If it's an even page, capture the output. This
|
||||||
// illustrates that you may capture any output generated
|
// illustrates that you may capture any output generated
|
||||||
// by the filter, or you may ignore it.
|
// by the filter, or you may ignore it.
|
||||||
StringCounter counter;
|
StringCounter counter;
|
||||||
if (pageno % 2)
|
if (pageno % 2) {
|
||||||
{
|
|
||||||
// Ignore output for odd pages.
|
// Ignore output for odd pages.
|
||||||
page.filterContents(&counter);
|
page.filterContents(&counter);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Write output to stdout for even pages.
|
// Write output to stdout for even pages.
|
||||||
Pl_StdioFile out("stdout", stdout);
|
Pl_StdioFile out("stdout", stdout);
|
||||||
std::cout << "% Contents of page " << pageno << std::endl;
|
std::cout << "% Contents of page " << pageno << std::endl;
|
||||||
@ -110,9 +104,7 @@ int main(int argc, char* argv[])
|
|||||||
std::cout << "Page " << pageno
|
std::cout << "Page " << pageno
|
||||||
<< ": strings = " << counter.getCount() << std::endl;
|
<< ": strings = " << counter.getCount() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -5,20 +5,20 @@
|
|||||||
// StreamDataProvider with different types of filters.
|
// StreamDataProvider with different types of filters.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <qpdf/Pl_Buffer.hh>
|
||||||
|
#include <qpdf/Pl_DCT.hh>
|
||||||
|
#include <qpdf/Pl_RunLength.hh>
|
||||||
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/Pl_Buffer.hh>
|
|
||||||
#include <qpdf/Pl_RunLength.hh>
|
|
||||||
#include <qpdf/Pl_DCT.hh>
|
|
||||||
#include <qpdf/QIntC.hh>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
@ -27,11 +27,10 @@ static char const* whoami = 0;
|
|||||||
class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageProvider(std::string const& color_space,
|
ImageProvider(std::string const& color_space, std::string const& filter);
|
||||||
std::string const& filter);
|
|
||||||
virtual ~ImageProvider();
|
virtual ~ImageProvider();
|
||||||
virtual void provideStreamData(int objid, int generation,
|
virtual void
|
||||||
Pipeline* pipeline);
|
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
||||||
size_t getWidth() const;
|
size_t getWidth() const;
|
||||||
size_t getHeight() const;
|
size_t getHeight() const;
|
||||||
|
|
||||||
@ -45,8 +44,8 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
|||||||
J_COLOR_SPACE j_color_space;
|
J_COLOR_SPACE j_color_space;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageProvider::ImageProvider(std::string const& color_space,
|
ImageProvider::ImageProvider(
|
||||||
std::string const& filter) :
|
std::string const& color_space, std::string const& filter) :
|
||||||
width(400),
|
width(400),
|
||||||
stripe_height(80),
|
stripe_height(80),
|
||||||
color_space(color_space),
|
color_space(color_space),
|
||||||
@ -54,8 +53,7 @@ ImageProvider::ImageProvider(std::string const& color_space,
|
|||||||
n_stripes(6),
|
n_stripes(6),
|
||||||
j_color_space(JCS_UNKNOWN)
|
j_color_space(JCS_UNKNOWN)
|
||||||
{
|
{
|
||||||
if (color_space == "/DeviceCMYK")
|
if (color_space == "/DeviceCMYK") {
|
||||||
{
|
|
||||||
j_color_space = JCS_CMYK;
|
j_color_space = JCS_CMYK;
|
||||||
stripes.push_back(std::string("\xff\x00\x00\x00", 4));
|
stripes.push_back(std::string("\xff\x00\x00\x00", 4));
|
||||||
stripes.push_back(std::string("\x00\xff\x00\x00", 4));
|
stripes.push_back(std::string("\x00\xff\x00\x00", 4));
|
||||||
@ -63,9 +61,7 @@ ImageProvider::ImageProvider(std::string const& color_space,
|
|||||||
stripes.push_back(std::string("\xff\x00\xff\x00", 4));
|
stripes.push_back(std::string("\xff\x00\xff\x00", 4));
|
||||||
stripes.push_back(std::string("\xff\xff\x00\x00", 4));
|
stripes.push_back(std::string("\xff\xff\x00\x00", 4));
|
||||||
stripes.push_back(std::string("\x00\x00\x00\xff", 4));
|
stripes.push_back(std::string("\x00\x00\x00\xff", 4));
|
||||||
}
|
} else if (color_space == "/DeviceRGB") {
|
||||||
else if (color_space == "/DeviceRGB")
|
|
||||||
{
|
|
||||||
j_color_space = JCS_RGB;
|
j_color_space = JCS_RGB;
|
||||||
stripes.push_back(std::string("\xff\x00\x00", 3));
|
stripes.push_back(std::string("\xff\x00\x00", 3));
|
||||||
stripes.push_back(std::string("\x00\xff\x00", 3));
|
stripes.push_back(std::string("\x00\xff\x00", 3));
|
||||||
@ -73,9 +69,7 @@ ImageProvider::ImageProvider(std::string const& color_space,
|
|||||||
stripes.push_back(std::string("\xff\x00\xff", 3));
|
stripes.push_back(std::string("\xff\x00\xff", 3));
|
||||||
stripes.push_back(std::string("\xff\xff\x00", 3));
|
stripes.push_back(std::string("\xff\xff\x00", 3));
|
||||||
stripes.push_back(std::string("\x00\x00\x00", 3));
|
stripes.push_back(std::string("\x00\x00\x00", 3));
|
||||||
}
|
} else if (color_space == "/DeviceGray") {
|
||||||
else if (color_space == "/DeviceGray")
|
|
||||||
{
|
|
||||||
j_color_space = JCS_GRAYSCALE;
|
j_color_space = JCS_GRAYSCALE;
|
||||||
stripes.push_back(std::string("\xee", 1));
|
stripes.push_back(std::string("\xee", 1));
|
||||||
stripes.push_back(std::string("\xcc", 1));
|
stripes.push_back(std::string("\xcc", 1));
|
||||||
@ -103,34 +97,31 @@ ImageProvider::getHeight() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageProvider::provideStreamData(int objid, int generation,
|
ImageProvider::provideStreamData(int objid, int generation, Pipeline* pipeline)
|
||||||
Pipeline* pipeline)
|
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
||||||
Pipeline* p = pipeline;
|
Pipeline* p = pipeline;
|
||||||
std::shared_ptr<Pipeline> p_new;
|
std::shared_ptr<Pipeline> p_new;
|
||||||
|
|
||||||
if (filter == "/DCTDecode")
|
if (filter == "/DCTDecode") {
|
||||||
{
|
|
||||||
p_new = std::make_shared<Pl_DCT>(
|
p_new = std::make_shared<Pl_DCT>(
|
||||||
"image encoder", pipeline,
|
"image encoder",
|
||||||
QIntC::to_uint(width), QIntC::to_uint(getHeight()),
|
pipeline,
|
||||||
QIntC::to_int(stripes[0].length()), j_color_space);
|
QIntC::to_uint(width),
|
||||||
|
QIntC::to_uint(getHeight()),
|
||||||
|
QIntC::to_int(stripes[0].length()),
|
||||||
|
j_color_space);
|
||||||
to_delete.push_back(p_new);
|
to_delete.push_back(p_new);
|
||||||
p = p_new.get();
|
p = p_new.get();
|
||||||
}
|
} else if (filter == "/RunLengthDecode") {
|
||||||
else if (filter == "/RunLengthDecode")
|
|
||||||
{
|
|
||||||
p_new = std::make_shared<Pl_RunLength>(
|
p_new = std::make_shared<Pl_RunLength>(
|
||||||
"image encoder", pipeline, Pl_RunLength::a_encode);
|
"image encoder", pipeline, Pl_RunLength::a_encode);
|
||||||
to_delete.push_back(p_new);
|
to_delete.push_back(p_new);
|
||||||
p = p_new.get();
|
p = p_new.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < n_stripes; ++i)
|
for (size_t i = 0; i < n_stripes; ++i) {
|
||||||
{
|
for (size_t j = 0; j < width * stripe_height; ++j) {
|
||||||
for (size_t j = 0; j < width * stripe_height; ++j)
|
|
||||||
{
|
|
||||||
p->write(
|
p->write(
|
||||||
QUtil::unsigned_char_pointer(stripes[i].c_str()),
|
QUtil::unsigned_char_pointer(stripes[i].c_str()),
|
||||||
stripes[i].length());
|
stripes[i].length());
|
||||||
@ -139,36 +130,43 @@ ImageProvider::provideStreamData(int objid, int generation,
|
|||||||
p->finish();
|
p->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " filename" << std::endl
|
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);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QPDFObjectHandle createPageContents(QPDF& pdf, std::string const& text)
|
static QPDFObjectHandle
|
||||||
|
createPageContents(QPDF& pdf, std::string const& text)
|
||||||
{
|
{
|
||||||
// Create a stream that displays our image and the given text in
|
// Create a stream that displays our image and the given text in
|
||||||
// our font.
|
// our font.
|
||||||
std::string contents =
|
std::string contents = "BT /F1 24 Tf 72 320 Td (" + text +
|
||||||
"BT /F1 24 Tf 72 320 Td (" + text + ") Tj ET\n"
|
") Tj ET\n"
|
||||||
"q 244 0 0 144 184 100 cm /Im1 Do Q\n";
|
"q 244 0 0 144 184 100 cm /Im1 Do Q\n";
|
||||||
return QPDFObjectHandle::newStream(&pdf, contents);
|
return QPDFObjectHandle::newStream(&pdf, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle newName(std::string const& name)
|
QPDFObjectHandle
|
||||||
|
newName(std::string const& name)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::newName(name);
|
return QPDFObjectHandle::newName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle newInteger(size_t val)
|
QPDFObjectHandle
|
||||||
|
newInteger(size_t val)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::newInteger(QIntC::to_int(val));
|
return QPDFObjectHandle::newInteger(QIntC::to_int(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_page(QPDFPageDocumentHelper& dh, QPDFObjectHandle font,
|
void
|
||||||
std::string const& color_space,
|
add_page(
|
||||||
std::string const& filter)
|
QPDFPageDocumentHelper& dh,
|
||||||
|
QPDFObjectHandle font,
|
||||||
|
std::string const& color_space,
|
||||||
|
std::string const& filter)
|
||||||
{
|
{
|
||||||
QPDF& pdf(dh.getQPDF());
|
QPDF& pdf(dh.getQPDF());
|
||||||
|
|
||||||
@ -193,9 +191,8 @@ void add_page(QPDFPageDocumentHelper& dh, QPDFObjectHandle font,
|
|||||||
image.replaceDict(image_dict);
|
image.replaceDict(image_dict);
|
||||||
|
|
||||||
// Provide the stream data.
|
// Provide the stream data.
|
||||||
image.replaceStreamData(provider,
|
image.replaceStreamData(
|
||||||
QPDFObjectHandle::parse(filter),
|
provider, QPDFObjectHandle::parse(filter), QPDFObjectHandle::newNull());
|
||||||
QPDFObjectHandle::newNull());
|
|
||||||
|
|
||||||
// Create direct objects as needed by the page dictionary.
|
// Create direct objects as needed by the page dictionary.
|
||||||
QPDFObjectHandle procset = "[/PDF /Text /ImageC]"_qpdf;
|
QPDFObjectHandle procset = "[/PDF /Text /ImageC]"_qpdf;
|
||||||
@ -212,15 +209,14 @@ void add_page(QPDFPageDocumentHelper& dh, QPDFObjectHandle font,
|
|||||||
resources.replaceKey("/XObject", xobject);
|
resources.replaceKey("/XObject", xobject);
|
||||||
|
|
||||||
// Create the page content stream
|
// Create the page content stream
|
||||||
QPDFObjectHandle contents = createPageContents(
|
QPDFObjectHandle contents =
|
||||||
pdf, color_space + " with filter " + filter);
|
createPageContents(pdf, color_space + " with filter " + filter);
|
||||||
|
|
||||||
// Create the page dictionary
|
// Create the page dictionary
|
||||||
QPDFObjectHandle page = pdf.makeIndirectObject(
|
QPDFObjectHandle page = pdf.makeIndirectObject("<<"
|
||||||
"<<"
|
" /Type /Page"
|
||||||
" /Type /Page"
|
" /MediaBox [0 0 612 392]"
|
||||||
" /MediaBox [0 0 612 392]"
|
">>"_qpdf);
|
||||||
">>"_qpdf);
|
|
||||||
page.replaceKey("/Contents", contents);
|
page.replaceKey("/Contents", contents);
|
||||||
page.replaceKey("/Resources", resources);
|
page.replaceKey("/Resources", resources);
|
||||||
|
|
||||||
@ -228,9 +224,11 @@ void add_page(QPDFPageDocumentHelper& dh, QPDFObjectHandle font,
|
|||||||
dh.addPage(page, false);
|
dh.addPage(page, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check(char const* filename,
|
static void
|
||||||
std::vector<std::string> const& color_spaces,
|
check(
|
||||||
std::vector<std::string> const& filters)
|
char const* filename,
|
||||||
|
std::vector<std::string> const& color_spaces,
|
||||||
|
std::vector<std::string> const& filters)
|
||||||
{
|
{
|
||||||
// Each stream is compressed the way it is supposed to be. We will
|
// Each stream is compressed the way it is supposed to be. We will
|
||||||
// add additional tests in qpdf.test to exercise QPDFWriter more
|
// add additional tests in qpdf.test to exercise QPDFWriter more
|
||||||
@ -253,17 +251,14 @@ static void check(char const* filename,
|
|||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
pdf.processFile(filename);
|
pdf.processFile(filename);
|
||||||
auto pages = QPDFPageDocumentHelper(pdf).getAllPages();
|
auto pages = QPDFPageDocumentHelper(pdf).getAllPages();
|
||||||
if (n_color_spaces * n_filters != pages.size())
|
if (n_color_spaces * n_filters != pages.size()) {
|
||||||
{
|
|
||||||
throw std::logic_error("incorrect number of pages");
|
throw std::logic_error("incorrect number of pages");
|
||||||
}
|
}
|
||||||
size_t pageno = 1;
|
size_t pageno = 1;
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
for (auto& page : pages)
|
for (auto& page : pages) {
|
||||||
{
|
|
||||||
auto images = page.getImages();
|
auto images = page.getImages();
|
||||||
if (images.size() != 1)
|
if (images.size() != 1) {
|
||||||
{
|
|
||||||
throw std::logic_error("incorrect number of images on page");
|
throw std::logic_error("incorrect number of images on page");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,8 +268,7 @@ static void check(char const* filename,
|
|||||||
std::string desired_filter = filters[(pageno - 1) % n_filters];
|
std::string desired_filter = filters[(pageno - 1) % n_filters];
|
||||||
// In the default mode, QPDFWriter will compress with
|
// In the default mode, QPDFWriter will compress with
|
||||||
// /FlateDecode if no filters are provided.
|
// /FlateDecode if no filters are provided.
|
||||||
if (desired_filter == "null")
|
if (desired_filter == "null") {
|
||||||
{
|
|
||||||
desired_filter = "/FlateDecode";
|
desired_filter = "/FlateDecode";
|
||||||
}
|
}
|
||||||
QPDFObjectHandle image = images.begin()->second;
|
QPDFObjectHandle image = images.begin()->second;
|
||||||
@ -282,40 +276,34 @@ static void check(char const* filename,
|
|||||||
QPDFObjectHandle color_space = image_dict.getKey("/ColorSpace");
|
QPDFObjectHandle color_space = image_dict.getKey("/ColorSpace");
|
||||||
QPDFObjectHandle filter = image_dict.getKey("/Filter");
|
QPDFObjectHandle filter = image_dict.getKey("/Filter");
|
||||||
bool this_errors = false;
|
bool this_errors = false;
|
||||||
if (! filter.isNameAndEquals(desired_filter))
|
if (!filter.isNameAndEquals(desired_filter)) {
|
||||||
{
|
|
||||||
this_errors = errors = true;
|
this_errors = errors = true;
|
||||||
std::cout << "page " << pageno << ": expected filter "
|
std::cout << "page " << pageno << ": expected filter "
|
||||||
<< desired_filter << "; actual filter = "
|
<< desired_filter
|
||||||
<< filter.unparse() << std::endl;
|
<< "; actual filter = " << filter.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
if (! color_space.isNameAndEquals(desired_color_space))
|
if (!color_space.isNameAndEquals(desired_color_space)) {
|
||||||
{
|
|
||||||
this_errors = errors = true;
|
this_errors = errors = true;
|
||||||
std::cout << "page " << pageno << ": expected color space "
|
std::cout << "page " << pageno << ": expected color space "
|
||||||
<< desired_color_space << "; actual color space = "
|
<< desired_color_space
|
||||||
<< color_space.unparse() << std::endl;
|
<< "; actual color space = " << color_space.unparse()
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! this_errors)
|
if (!this_errors) {
|
||||||
{
|
|
||||||
// Check image data
|
// Check image data
|
||||||
auto actual_data =
|
auto actual_data = image.getStreamData(qpdf_dl_all);
|
||||||
image.getStreamData(qpdf_dl_all);
|
|
||||||
ImageProvider* p = new ImageProvider(desired_color_space, "null");
|
ImageProvider* p = new ImageProvider(desired_color_space, "null");
|
||||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> provider(p);
|
PointerHolder<QPDFObjectHandle::StreamDataProvider> provider(p);
|
||||||
Pl_Buffer b_p("get image data");
|
Pl_Buffer b_p("get image data");
|
||||||
provider->provideStreamData(0, 0, &b_p);
|
provider->provideStreamData(0, 0, &b_p);
|
||||||
PointerHolder<Buffer> desired_data(b_p.getBuffer());
|
PointerHolder<Buffer> desired_data(b_p.getBuffer());
|
||||||
|
|
||||||
if (desired_data->getSize() != actual_data->getSize())
|
if (desired_data->getSize() != actual_data->getSize()) {
|
||||||
{
|
std::cout << "page " << pageno << ": image data length mismatch"
|
||||||
std::cout << "page " << pageno
|
<< std::endl;
|
||||||
<< ": image data length mismatch" << std::endl;
|
|
||||||
this_errors = errors = true;
|
this_errors = errors = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Compare bytes. For JPEG, allow a certain number of
|
// Compare bytes. For JPEG, allow a certain number of
|
||||||
// the bytes to be off desired by more than a given
|
// the bytes to be off desired by more than a given
|
||||||
// tolerance. Any of the samples may be a little off
|
// tolerance. Any of the samples may be a little off
|
||||||
@ -326,25 +314,20 @@ static void check(char const* filename,
|
|||||||
unsigned char const* desired_bytes = desired_data->getBuffer();
|
unsigned char const* desired_bytes = desired_data->getBuffer();
|
||||||
size_t len = actual_data->getSize();
|
size_t len = actual_data->getSize();
|
||||||
unsigned int mismatches = 0;
|
unsigned int mismatches = 0;
|
||||||
int tolerance = (
|
int tolerance = (desired_filter == "/DCTDecode" ? 10 : 0);
|
||||||
desired_filter == "/DCTDecode" ? 10 : 0);
|
size_t threshold =
|
||||||
size_t threshold = (
|
(desired_filter == "/DCTDecode" ? len / 40U : 0);
|
||||||
desired_filter == "/DCTDecode" ? len / 40U : 0);
|
for (size_t i = 0; i < len; ++i) {
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
int delta = actual_bytes[i] - desired_bytes[i];
|
int delta = actual_bytes[i] - desired_bytes[i];
|
||||||
if ((delta > tolerance) || (delta < -tolerance))
|
if ((delta > tolerance) || (delta < -tolerance)) {
|
||||||
{
|
|
||||||
++mismatches;
|
++mismatches;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mismatches > threshold)
|
if (mismatches > threshold) {
|
||||||
{
|
std::cout << "page " << pageno << ": "
|
||||||
std::cout << "page " << pageno
|
<< desired_color_space << ", " << desired_filter
|
||||||
<< ": " << desired_color_space << ", "
|
<< ": mismatches: " << mismatches << " of " << len
|
||||||
<< desired_filter
|
<< std::endl;
|
||||||
<< ": mismatches: " << mismatches
|
|
||||||
<< " of " << len << std::endl;
|
|
||||||
this_errors = errors = true;
|
this_errors = errors = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,17 +335,15 @@ static void check(char const* filename,
|
|||||||
|
|
||||||
++pageno;
|
++pageno;
|
||||||
}
|
}
|
||||||
if (errors)
|
if (errors) {
|
||||||
{
|
|
||||||
throw std::logic_error("errors found");
|
throw std::logic_error("errors found");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "all checks passed" << std::endl;
|
std::cout << "all checks passed" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_pdf(char const* filename)
|
static void
|
||||||
|
create_pdf(char const* filename)
|
||||||
{
|
{
|
||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
|
|
||||||
@ -371,14 +352,13 @@ static void create_pdf(char const* filename)
|
|||||||
|
|
||||||
// Add an indirect object to contain a font descriptor for the
|
// Add an indirect object to contain a font descriptor for the
|
||||||
// built-in Helvetica font.
|
// built-in Helvetica font.
|
||||||
QPDFObjectHandle font = pdf.makeIndirectObject(
|
QPDFObjectHandle font = pdf.makeIndirectObject("<<"
|
||||||
"<<"
|
" /Type /Font"
|
||||||
" /Type /Font"
|
" /Subtype /Type1"
|
||||||
" /Subtype /Type1"
|
" /Name /F1"
|
||||||
" /Name /F1"
|
" /BaseFont /Helvetica"
|
||||||
" /BaseFont /Helvetica"
|
" /Encoding /WinAnsiEncoding"
|
||||||
" /Encoding /WinAnsiEncoding"
|
">>"_qpdf);
|
||||||
">>"_qpdf);
|
|
||||||
|
|
||||||
std::vector<std::string> color_spaces;
|
std::vector<std::string> color_spaces;
|
||||||
color_spaces.push_back("/DeviceCMYK");
|
color_spaces.push_back("/DeviceCMYK");
|
||||||
@ -389,10 +369,8 @@ static void create_pdf(char const* filename)
|
|||||||
filters.push_back("/DCTDecode");
|
filters.push_back("/DCTDecode");
|
||||||
filters.push_back("/RunLengthDecode");
|
filters.push_back("/RunLengthDecode");
|
||||||
QPDFPageDocumentHelper dh(pdf);
|
QPDFPageDocumentHelper dh(pdf);
|
||||||
for (auto const& color_space : color_spaces)
|
for (auto const& color_space : color_spaces) {
|
||||||
{
|
for (auto const& filter : filters) {
|
||||||
for (auto const& filter : filters)
|
|
||||||
{
|
|
||||||
add_page(dh, font, color_space, filter);
|
add_page(dh, font, color_space, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,22 +383,19 @@ static void create_pdf(char const* filename)
|
|||||||
check(filename, color_spaces, filters);
|
check(filename, color_spaces, filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
char const* filename = argv[1];
|
char const* filename = argv[1];
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
create_pdf(filename);
|
create_pdf(filename);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QPDFWriter.hh>
|
|
||||||
#include <qpdf/QPDFStreamFilter.hh>
|
#include <qpdf/QPDFStreamFilter.hh>
|
||||||
|
#include <qpdf/QPDFWriter.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
@ -39,7 +39,6 @@
|
|||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
|
|
||||||
class Pl_XOR: public Pipeline
|
class Pl_XOR: public Pipeline
|
||||||
{
|
{
|
||||||
// This class implements a Pipeline for the made-up XOR decoder.
|
// This class implements a Pipeline for the made-up XOR decoder.
|
||||||
@ -66,8 +65,7 @@ Pl_XOR::Pl_XOR(char const* identifier, Pipeline* next, unsigned char key) :
|
|||||||
void
|
void
|
||||||
Pl_XOR::write(unsigned char* data, size_t len)
|
Pl_XOR::write(unsigned char* data, size_t len)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < len; ++i)
|
for (size_t i = 0; i < len; ++i) {
|
||||||
{
|
|
||||||
unsigned char p = data[i] ^ this->key;
|
unsigned char p = data[i] ^ this->key;
|
||||||
getNext()->write(&p, 1);
|
getNext()->write(&p, 1);
|
||||||
}
|
}
|
||||||
@ -118,8 +116,7 @@ SF_XORDecode::setDecodeParms(QPDFObjectHandle decode_parms)
|
|||||||
// to handle the /JBIG2Globals key, which points to a stream. See
|
// to handle the /JBIG2Globals key, which points to a stream. See
|
||||||
// comments in SF_XORDecode::registerStream for additional notes
|
// comments in SF_XORDecode::registerStream for additional notes
|
||||||
// on this.
|
// on this.
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// Expect /DecodeParms to be a dictionary with a /KeyStream
|
// Expect /DecodeParms to be a dictionary with a /KeyStream
|
||||||
// key that points to a one-byte stream whose single byte is
|
// key that points to a one-byte stream whose single byte is
|
||||||
// the key. If we are successful at retrieving the key, return
|
// the key. If we are successful at retrieving the key, return
|
||||||
@ -129,17 +126,14 @@ SF_XORDecode::setDecodeParms(QPDFObjectHandle decode_parms)
|
|||||||
// implementations, look at the classes whose names start with
|
// implementations, look at the classes whose names start with
|
||||||
// SF_ in the qpdf library implementation.
|
// SF_ in the qpdf library implementation.
|
||||||
auto buf = decode_parms.getKey("/KeyStream").getStreamData();
|
auto buf = decode_parms.getKey("/KeyStream").getStreamData();
|
||||||
if (buf->getSize() != 1)
|
if (buf->getSize() != 1) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this->key = buf->getBuffer()[0];
|
this->key = buf->getBuffer()[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
std::cerr << "Error extracting key for /XORDecode: " << e.what()
|
||||||
{
|
<< std::endl;
|
||||||
std::cerr << "Error extracting key for /XORDecode: "
|
|
||||||
<< e.what() << std::endl;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -206,17 +200,19 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
|
|||||||
public:
|
public:
|
||||||
StreamReplacer(QPDF* pdf);
|
StreamReplacer(QPDF* pdf);
|
||||||
virtual ~StreamReplacer() = default;
|
virtual ~StreamReplacer() = default;
|
||||||
virtual void provideStreamData(int objid, int generation,
|
virtual void
|
||||||
Pipeline* pipeline) override;
|
provideStreamData(int objid, int generation, Pipeline* pipeline) override;
|
||||||
|
|
||||||
void registerStream(
|
void registerStream(
|
||||||
QPDFObjectHandle stream,
|
QPDFObjectHandle stream,
|
||||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> self);
|
PointerHolder<QPDFObjectHandle::StreamDataProvider> self);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool maybeReplace(QPDFObjGen const& og,
|
bool maybeReplace(
|
||||||
QPDFObjectHandle& stream, Pipeline* pipeline,
|
QPDFObjGen const& og,
|
||||||
QPDFObjectHandle* dict_updates);
|
QPDFObjectHandle& stream,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
QPDFObjectHandle* dict_updates);
|
||||||
|
|
||||||
// Hang onto a reference to the QPDF object containing the streams
|
// Hang onto a reference to the QPDF object containing the streams
|
||||||
// we are replacing. We need this to create a new stream.
|
// we are replacing. We need this to create a new stream.
|
||||||
@ -238,10 +234,11 @@ StreamReplacer::StreamReplacer(QPDF* pdf) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
StreamReplacer::maybeReplace(QPDFObjGen const& og,
|
StreamReplacer::maybeReplace(
|
||||||
QPDFObjectHandle& stream,
|
QPDFObjGen const& og,
|
||||||
Pipeline* pipeline,
|
QPDFObjectHandle& stream,
|
||||||
QPDFObjectHandle* dict_updates)
|
Pipeline* pipeline,
|
||||||
|
QPDFObjectHandle* dict_updates)
|
||||||
{
|
{
|
||||||
// As described in the class comments, this method is called
|
// As described in the class comments, this method is called
|
||||||
// twice. Before writing has started pipeline is nullptr, and
|
// twice. Before writing has started pipeline is nullptr, and
|
||||||
@ -276,8 +273,7 @@ StreamReplacer::maybeReplace(QPDFObjGen const& og,
|
|||||||
// density.
|
// density.
|
||||||
auto dict = stream.getDict();
|
auto dict = stream.getDict();
|
||||||
auto mark = dict.getKey("/DoXOR");
|
auto mark = dict.getKey("/DoXOR");
|
||||||
if (! (mark.isBool() && mark.getBoolValue()))
|
if (!(mark.isBool() && mark.getBoolValue())) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,17 +284,13 @@ StreamReplacer::maybeReplace(QPDFObjGen const& og,
|
|||||||
// it's a good idea to make sure we can retrieve the filtered data
|
// it's a good idea to make sure we can retrieve the filtered data
|
||||||
// if we are going to need it later.
|
// if we are going to need it later.
|
||||||
PointerHolder<Buffer> out;
|
PointerHolder<Buffer> out;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
out = stream.getStreamData();
|
out = stream.getStreamData();
|
||||||
}
|
} catch (...) {
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict_updates)
|
if (dict_updates) {
|
||||||
{
|
|
||||||
// It's not safe to make any modifications to any objects
|
// It's not safe to make any modifications to any objects
|
||||||
// during the writing process since the updated objects may
|
// during the writing process since the updated objects may
|
||||||
// have already been written. In this mode, when dict_updates
|
// have already been written. In this mode, when dict_updates
|
||||||
@ -309,16 +301,15 @@ StreamReplacer::maybeReplace(QPDFObjGen const& og,
|
|||||||
// changes. For example, an image resampler might change the
|
// changes. For example, an image resampler might change the
|
||||||
// dimensions or other properties of the image.
|
// dimensions or other properties of the image.
|
||||||
dict_updates->replaceKey(
|
dict_updates->replaceKey(
|
||||||
"/OrigLength", QPDFObjectHandle::newInteger(
|
"/OrigLength",
|
||||||
QIntC::to_longlong(out->getSize())));
|
QPDFObjectHandle::newInteger(QIntC::to_longlong(out->getSize())));
|
||||||
// We are also storing the "key" that we will access when
|
// We are also storing the "key" that we will access when
|
||||||
// writing the data.
|
// writing the data.
|
||||||
this->keys[og] = QIntC::to_uchar(
|
this->keys[og] = QIntC::to_uchar(
|
||||||
(og.getObj() * QIntC::to_int(out->getSize())) & 0xff);
|
(og.getObj() * QIntC::to_int(out->getSize())) & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipeline)
|
if (pipeline) {
|
||||||
{
|
|
||||||
unsigned char key = this->keys[og];
|
unsigned char key = this->keys[og];
|
||||||
Pl_XOR p("xor", pipeline, key);
|
Pl_XOR p("xor", pipeline, key);
|
||||||
p.write(out->getBuffer(), out->getSize());
|
p.write(out->getBuffer(), out->getSize());
|
||||||
@ -338,8 +329,7 @@ StreamReplacer::registerStream(
|
|||||||
// example, we are just iterating through objects, but if we were
|
// example, we are just iterating through objects, but if we were
|
||||||
// doing something like iterating through images on pages, we
|
// doing something like iterating through images on pages, we
|
||||||
// might realistically encounter the same stream more than once.
|
// might realistically encounter the same stream more than once.
|
||||||
if (this->copied_streams.count(og) > 0)
|
if (this->copied_streams.count(og) > 0) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Store something in copied_streams so that we don't
|
// Store something in copied_streams so that we don't
|
||||||
@ -352,19 +342,14 @@ StreamReplacer::registerStream(
|
|||||||
// so, supplies dictionary updates we should make.
|
// so, supplies dictionary updates we should make.
|
||||||
bool should_replace = false;
|
bool should_replace = false;
|
||||||
QPDFObjectHandle dict_updates = QPDFObjectHandle::newDictionary();
|
QPDFObjectHandle dict_updates = QPDFObjectHandle::newDictionary();
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
should_replace = maybeReplace(og, stream, nullptr, &dict_updates);
|
should_replace = maybeReplace(og, stream, nullptr, &dict_updates);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
stream.warnIfPossible(
|
stream.warnIfPossible(
|
||||||
std::string("exception while attempting to replace: ") +
|
std::string("exception while attempting to replace: ") + e.what());
|
||||||
e.what());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_replace)
|
if (should_replace) {
|
||||||
{
|
|
||||||
// Copy the stream so we can get to the original data from the
|
// Copy the stream so we can get to the original data from the
|
||||||
// stream data provider. This doesn't actually copy any data,
|
// stream data provider. This doesn't actually copy any data,
|
||||||
// but the copy retains the original stream data after the
|
// but the copy retains the original stream data after the
|
||||||
@ -372,14 +357,13 @@ StreamReplacer::registerStream(
|
|||||||
this->copied_streams[og] = stream.copyStream();
|
this->copied_streams[og] = stream.copyStream();
|
||||||
// Update the stream dictionary with any changes.
|
// Update the stream dictionary with any changes.
|
||||||
auto dict = stream.getDict();
|
auto dict = stream.getDict();
|
||||||
for (auto const& k: dict_updates.getKeys())
|
for (auto const& k : dict_updates.getKeys()) {
|
||||||
{
|
|
||||||
dict.replaceKey(k, dict_updates.getKey(k));
|
dict.replaceKey(k, dict_updates.getKey(k));
|
||||||
}
|
}
|
||||||
// Create the key stream that will be referenced from
|
// Create the key stream that will be referenced from
|
||||||
// /DecodeParms. We have to do this now since you can't modify
|
// /DecodeParms. We have to do this now since you can't modify
|
||||||
// or create objects during write.
|
// or create objects during write.
|
||||||
char p[1] = { static_cast<char>(this->keys[og]) };
|
char p[1] = {static_cast<char>(this->keys[og])};
|
||||||
std::string p_str(p, 1);
|
std::string p_str(p, 1);
|
||||||
QPDFObjectHandle dp_stream =
|
QPDFObjectHandle dp_stream =
|
||||||
QPDFObjectHandle::newStream(this->pdf, p_str);
|
QPDFObjectHandle::newStream(this->pdf, p_str);
|
||||||
@ -388,23 +372,19 @@ StreamReplacer::registerStream(
|
|||||||
QPDFObjectHandle decode_parms =
|
QPDFObjectHandle decode_parms =
|
||||||
QPDFObjectHandle::newDictionary({{"/KeyStream", dp_stream}});
|
QPDFObjectHandle::newDictionary({{"/KeyStream", dp_stream}});
|
||||||
stream.replaceStreamData(
|
stream.replaceStreamData(
|
||||||
self,
|
self, QPDFObjectHandle::newName("/XORDecode"), decode_parms);
|
||||||
QPDFObjectHandle::newName("/XORDecode"),
|
|
||||||
decode_parms);
|
|
||||||
// Further, if /ProtectXOR = true, we disable filtering on write
|
// Further, if /ProtectXOR = true, we disable filtering on write
|
||||||
// so that QPDFWriter will not decode the stream even though we
|
// so that QPDFWriter will not decode the stream even though we
|
||||||
// have registered a stream filter for /XORDecode.
|
// have registered a stream filter for /XORDecode.
|
||||||
auto protect = dict.getKey("/ProtectXOR");
|
auto protect = dict.getKey("/ProtectXOR");
|
||||||
if (protect.isBool() && protect.getBoolValue())
|
if (protect.isBool() && protect.getBoolValue()) {
|
||||||
{
|
|
||||||
stream.setFilterOnWrite(false);
|
stream.setFilterOnWrite(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
StreamReplacer::provideStreamData(int objid, int generation,
|
StreamReplacer::provideStreamData(int objid, int generation, Pipeline* pipeline)
|
||||||
Pipeline* pipeline)
|
|
||||||
{
|
{
|
||||||
QPDFObjGen og(objid, generation);
|
QPDFObjGen og(objid, generation);
|
||||||
QPDFObjectHandle orig = this->copied_streams[og];
|
QPDFObjectHandle orig = this->copied_streams[og];
|
||||||
@ -412,8 +392,7 @@ StreamReplacer::provideStreamData(int objid, int generation,
|
|||||||
// dict_updates. In this mode, maybeReplace doesn't make any
|
// dict_updates. In this mode, maybeReplace doesn't make any
|
||||||
// changes. We have to hand it the original stream data, which we
|
// changes. We have to hand it the original stream data, which we
|
||||||
// get from copied_streams.
|
// get from copied_streams.
|
||||||
if (! maybeReplace(og, orig, pipeline, nullptr))
|
if (!maybeReplace(og, orig, pipeline, nullptr)) {
|
||||||
{
|
|
||||||
// Since this only gets called for streams we already
|
// Since this only gets called for streams we already
|
||||||
// determined we are replacing, a false return would indicate
|
// determined we are replacing, a false return would indicate
|
||||||
// a logic error.
|
// a logic error.
|
||||||
@ -422,8 +401,9 @@ StreamReplacer::provideStreamData(int objid, int generation,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process(char const* infilename, char const* outfilename,
|
static void
|
||||||
bool decode_specialized)
|
process(
|
||||||
|
char const* infilename, char const* outfilename, bool decode_specialized)
|
||||||
{
|
{
|
||||||
QPDF qpdf;
|
QPDF qpdf;
|
||||||
qpdf.processFile(infilename);
|
qpdf.processFile(infilename);
|
||||||
@ -434,10 +414,8 @@ static void process(char const* infilename, char const* outfilename,
|
|||||||
StreamReplacer* replacer = new StreamReplacer(&qpdf);
|
StreamReplacer* replacer = new StreamReplacer(&qpdf);
|
||||||
PointerHolder<QPDFObjectHandle::StreamDataProvider> p(replacer);
|
PointerHolder<QPDFObjectHandle::StreamDataProvider> p(replacer);
|
||||||
|
|
||||||
for (auto& o: qpdf.getAllObjects())
|
for (auto& o : qpdf.getAllObjects()) {
|
||||||
{
|
if (o.isStream()) {
|
||||||
if (o.isStream())
|
|
||||||
{
|
|
||||||
// Call registerStream for every stream. Only ones that
|
// Call registerStream for every stream. Only ones that
|
||||||
// registerStream decides to replace will actually be
|
// registerStream decides to replace will actually be
|
||||||
// replaced.
|
// replaced.
|
||||||
@ -446,70 +424,58 @@ static void process(char const* infilename, char const* outfilename,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPDFWriter w(qpdf, outfilename);
|
QPDFWriter w(qpdf, outfilename);
|
||||||
if (decode_specialized)
|
if (decode_specialized) {
|
||||||
{
|
|
||||||
w.setDecodeLevel(qpdf_dl_specialized);
|
w.setDecodeLevel(qpdf_dl_specialized);
|
||||||
}
|
}
|
||||||
// For the test suite, use static IDs.
|
// For the test suite, use static IDs.
|
||||||
w.setStaticID(true); // for testing only
|
w.setStaticID(true); // for testing only
|
||||||
w.write();
|
w.write();
|
||||||
std::cout << whoami << ": new file written to " << outfilename
|
std::cout << whoami << ": new file written to " << outfilename << std::endl;
|
||||||
<< std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage()
|
static void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr
|
std::cerr << "\n"
|
||||||
<< "\n"
|
<< "Usage: " << whoami
|
||||||
<< "Usage: " << whoami << " [--decode-specialized] infile outfile\n"
|
<< " [--decode-specialized] infile outfile\n"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
char const* infilename = 0;
|
char const* infilename = 0;
|
||||||
char const* outfilename = 0;
|
char const* outfilename = 0;
|
||||||
bool decode_specialized = false;
|
bool decode_specialized = false;
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i) {
|
||||||
{
|
if (strcmp(argv[i], "--decode-specialized") == 0) {
|
||||||
if (strcmp(argv[i], "--decode-specialized") == 0)
|
|
||||||
{
|
|
||||||
decode_specialized = true;
|
decode_specialized = true;
|
||||||
}
|
} else if (!infilename) {
|
||||||
else if (! infilename)
|
|
||||||
{
|
|
||||||
infilename = argv[i];
|
infilename = argv[i];
|
||||||
}
|
} else if (!outfilename) {
|
||||||
else if (! outfilename)
|
|
||||||
{
|
|
||||||
outfilename = argv[i];
|
outfilename = argv[i];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! (infilename && outfilename))
|
if (!(infilename && outfilename)) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// Register our fictitious filter. This enables QPDFWriter to
|
// Register our fictitious filter. This enables QPDFWriter to
|
||||||
// decode our streams. This is not a real filter, so no real
|
// decode our streams. This is not a real filter, so no real
|
||||||
// PDF reading application would be able to interpret it. This
|
// PDF reading application would be able to interpret it. This
|
||||||
// is just for illustrative purposes.
|
// is just for illustrative purposes.
|
||||||
QPDF::registerStreamFilter(
|
QPDF::registerStreamFilter(
|
||||||
"/XORDecode", []{ return std::make_shared<SF_XORDecode>(); });
|
"/XORDecode", [] { return std::make_shared<SF_XORDecode>(); });
|
||||||
// Do the actual processing.
|
// Do the actual processing.
|
||||||
process(infilename, outfilename, decode_specialized);
|
process(infilename, outfilename, decode_specialized);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": exception: " << e.what() << std::endl;
|
std::cerr << whoami << ": exception: " << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include <iostream>
|
#include <qpdf/Buffer.hh>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
@ -21,45 +22,43 @@ void usage()
|
|||||||
|
|
||||||
// If there is a box of name box_name, replace it with a new box whose
|
// If there is a box of name box_name, replace it with a new box whose
|
||||||
// elements are double the values of the original box.
|
// elements are double the values of the original box.
|
||||||
static void doubleBoxSize(QPDFPageObjectHelper& page, char const* box_name)
|
static void
|
||||||
|
doubleBoxSize(QPDFPageObjectHelper& page, char const* box_name)
|
||||||
{
|
{
|
||||||
// We need to use getAttribute rather than getKey as some boxes could
|
// We need to use getAttribute rather than getKey as some boxes could
|
||||||
// be inherited.
|
// be inherited.
|
||||||
auto box = page.getAttribute(box_name, true);
|
auto box = page.getAttribute(box_name, true);
|
||||||
if (box.isNull())
|
if (box.isNull()) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (! box.isRectangle())
|
if (!box.isRectangle()) {
|
||||||
{
|
throw std::runtime_error(
|
||||||
throw std::runtime_error(std::string("box ") + box_name +
|
std::string("box ") + box_name +
|
||||||
" is not an array of four elements");
|
" is not an array of four elements");
|
||||||
}
|
}
|
||||||
std::vector<QPDFObjectHandle> doubled;
|
std::vector<QPDFObjectHandle> doubled;
|
||||||
for (auto& item : box.aitems())
|
for (auto& item : box.aitems()) {
|
||||||
{
|
|
||||||
doubled.push_back(
|
doubled.push_back(
|
||||||
QPDFObjectHandle::newReal(item.getNumericValue() * 2.0, 2));
|
QPDFObjectHandle::newReal(item.getNumericValue() * 2.0, 2));
|
||||||
}
|
}
|
||||||
page.getObjectHandle()
|
page.getObjectHandle().replaceKey(
|
||||||
.replaceKey(box_name, QPDFObjectHandle::newArray(doubled));
|
box_name, QPDFObjectHandle::newArray(doubled));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
// For test suite
|
// For test suite
|
||||||
bool static_id = false;
|
bool static_id = false;
|
||||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0)) {
|
||||||
{
|
|
||||||
static_id = true;
|
static_id = true;
|
||||||
--argc;
|
--argc;
|
||||||
++argv;
|
++argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ((argc == 3) || (argc == 4)))
|
if (!((argc == 3) || (argc == 4))) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +69,11 @@ int main(int argc, char* argv[])
|
|||||||
// Text to prepend to each page's contents
|
// Text to prepend to each page's contents
|
||||||
std::string content = "2 0 0 2 0 0 cm\n";
|
std::string content = "2 0 0 2 0 0 cm\n";
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF qpdf;
|
QPDF qpdf;
|
||||||
qpdf.processFile(infilename, password);
|
qpdf.processFile(infilename, password);
|
||||||
|
|
||||||
for (auto& page : QPDFPageDocumentHelper(qpdf).getAllPages())
|
for (auto& page : QPDFPageDocumentHelper(qpdf).getAllPages()) {
|
||||||
{
|
|
||||||
// Prepend the buffer to the page's contents
|
// Prepend the buffer to the page's contents
|
||||||
page.addPageContents(
|
page.addPageContents(
|
||||||
QPDFObjectHandle::newStream(&qpdf, content), true);
|
QPDFObjectHandle::newStream(&qpdf, content), true);
|
||||||
@ -91,8 +88,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Write out a new file
|
// Write out a new file
|
||||||
QPDFWriter w(qpdf, outfilename);
|
QPDFWriter w(qpdf, outfilename);
|
||||||
if (static_id)
|
if (static_id) {
|
||||||
{
|
|
||||||
// For the test suite, uncompress streams and use static IDs.
|
// For the test suite, uncompress streams and use static IDs.
|
||||||
w.setStaticID(true); // for testing only
|
w.setStaticID(true); // for testing only
|
||||||
w.setStreamDataMode(qpdf_s_uncompress);
|
w.setStreamDataMode(qpdf_s_uncompress);
|
||||||
@ -100,9 +96,7 @@ int main(int argc, char* argv[])
|
|||||||
w.write();
|
w.write();
|
||||||
std::cout << whoami << ": new file written to " << outfilename
|
std::cout << whoami << ": new file written to " << outfilename
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << " processing file " << infilename << ": "
|
std::cerr << whoami << " processing file " << infilename << ": "
|
||||||
<< e.what() << std::endl;
|
<< e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -5,22 +5,23 @@
|
|||||||
// QPDFObjectHandle::TokenFilter with filterContents.
|
// QPDFObjectHandle::TokenFilter with filterContents.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile outfile" << std::endl
|
std::cerr << "Usage: " << whoami << " infile outfile" << std::endl
|
||||||
<< "Applies token filters to infile and writes outfile"
|
<< "Applies token filters to infile and writes outfile"
|
||||||
@ -52,14 +53,11 @@ StringReverser::handleToken(QPDFTokenizer::Token const& token)
|
|||||||
// strings. It's just intended to give a simple example of a
|
// strings. It's just intended to give a simple example of a
|
||||||
// pretty minimal filter and to show an example of writing a
|
// pretty minimal filter and to show an example of writing a
|
||||||
// constructed token.
|
// constructed token.
|
||||||
if (token.getType() == QPDFTokenizer::tt_string)
|
if (token.getType() == QPDFTokenizer::tt_string) {
|
||||||
{
|
|
||||||
std::string value = token.getValue();
|
std::string value = token.getValue();
|
||||||
std::reverse(value.begin(), value.end());
|
std::reverse(value.begin(), value.end());
|
||||||
writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, value));
|
writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, value));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
writeToken(token);
|
writeToken(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,15 +88,17 @@ class ColorToGray: public QPDFObjectHandle::TokenFilter
|
|||||||
bool
|
bool
|
||||||
ColorToGray::isNumeric(QPDFTokenizer::token_type_e token_type)
|
ColorToGray::isNumeric(QPDFTokenizer::token_type_e token_type)
|
||||||
{
|
{
|
||||||
return ((token_type == QPDFTokenizer::tt_integer) ||
|
return (
|
||||||
(token_type == QPDFTokenizer::tt_real));
|
(token_type == QPDFTokenizer::tt_integer) ||
|
||||||
|
(token_type == QPDFTokenizer::tt_real));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ColorToGray::isIgnorable(QPDFTokenizer::token_type_e token_type)
|
ColorToGray::isIgnorable(QPDFTokenizer::token_type_e token_type)
|
||||||
{
|
{
|
||||||
return ((token_type == QPDFTokenizer::tt_space) ||
|
return (
|
||||||
(token_type == QPDFTokenizer::tt_comment));
|
(token_type == QPDFTokenizer::tt_space) ||
|
||||||
|
(token_type == QPDFTokenizer::tt_comment));
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
@ -134,33 +134,28 @@ ColorToGray::handleToken(QPDFTokenizer::Token const& token)
|
|||||||
// kinds of operands, replace the command. Flush any additional
|
// kinds of operands, replace the command. Flush any additional
|
||||||
// accumulated tokens to keep the stack only four tokens deep.
|
// accumulated tokens to keep the stack only four tokens deep.
|
||||||
|
|
||||||
while ((! this->all_stack.empty()) &&
|
while ((!this->all_stack.empty()) &&
|
||||||
isIgnorable(this->all_stack.at(0).getType()))
|
isIgnorable(this->all_stack.at(0).getType())) {
|
||||||
{
|
|
||||||
writeToken(this->all_stack.at(0));
|
writeToken(this->all_stack.at(0));
|
||||||
this->all_stack.pop_front();
|
this->all_stack.pop_front();
|
||||||
}
|
}
|
||||||
this->all_stack.push_back(token);
|
this->all_stack.push_back(token);
|
||||||
QPDFTokenizer::token_type_e token_type = token.getType();
|
QPDFTokenizer::token_type_e token_type = token.getType();
|
||||||
if (! isIgnorable(token_type))
|
if (!isIgnorable(token_type)) {
|
||||||
{
|
|
||||||
this->stack.push_back(token);
|
this->stack.push_back(token);
|
||||||
if ((this->stack.size() == 4) &&
|
if ((this->stack.size() == 4) &&
|
||||||
(token == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "rg")) &&
|
(token == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "rg")) &&
|
||||||
(isNumeric(this->stack.at(0).getType())) &&
|
(isNumeric(this->stack.at(0).getType())) &&
|
||||||
(isNumeric(this->stack.at(1).getType())) &&
|
(isNumeric(this->stack.at(1).getType())) &&
|
||||||
(isNumeric(this->stack.at(2).getType())))
|
(isNumeric(this->stack.at(2).getType()))) {
|
||||||
{
|
|
||||||
double r = numericValue(this->stack.at(0));
|
double r = numericValue(this->stack.at(0));
|
||||||
double g = numericValue(this->stack.at(1));
|
double g = numericValue(this->stack.at(1));
|
||||||
double b = numericValue(this->stack.at(2));
|
double b = numericValue(this->stack.at(2));
|
||||||
double gray = ((0.3 * r) + (0.59 * b) + (0.11 * g));
|
double gray = ((0.3 * r) + (0.59 * b) + (0.11 * g));
|
||||||
if (gray > 1.0)
|
if (gray > 1.0) {
|
||||||
{
|
|
||||||
gray = 1.0;
|
gray = 1.0;
|
||||||
}
|
}
|
||||||
if (gray < 0.0)
|
if (gray < 0.0) {
|
||||||
{
|
|
||||||
gray = 0.0;
|
gray = 0.0;
|
||||||
}
|
}
|
||||||
write(QUtil::double_to_string(gray, 3));
|
write(QUtil::double_to_string(gray, 3));
|
||||||
@ -169,8 +164,7 @@ ColorToGray::handleToken(QPDFTokenizer::Token const& token)
|
|||||||
this->all_stack.clear();
|
this->all_stack.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this->stack.size() == 4)
|
if (this->stack.size() == 4) {
|
||||||
{
|
|
||||||
writeToken(this->all_stack.at(0));
|
writeToken(this->all_stack.at(0));
|
||||||
this->all_stack.pop_front();
|
this->all_stack.pop_front();
|
||||||
this->stack.pop_front();
|
this->stack.pop_front();
|
||||||
@ -181,33 +175,31 @@ void
|
|||||||
ColorToGray::handleEOF()
|
ColorToGray::handleEOF()
|
||||||
{
|
{
|
||||||
// Flush out any remaining accumulated tokens.
|
// Flush out any remaining accumulated tokens.
|
||||||
while (! this->all_stack.empty())
|
while (!this->all_stack.empty()) {
|
||||||
{
|
|
||||||
writeToken(this->all_stack.at(0));
|
writeToken(this->all_stack.at(0));
|
||||||
this->all_stack.pop_front();
|
this->all_stack.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 3) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
char const* infilename = argv[1];
|
char const* infilename = argv[1];
|
||||||
char const* outfilename = argv[2];
|
char const* outfilename = argv[2];
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
pdf.processFile(infilename);
|
pdf.processFile(infilename);
|
||||||
std::vector<QPDFPageObjectHelper> pages =
|
std::vector<QPDFPageObjectHelper> pages =
|
||||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||||
iter != pages.end(); ++iter)
|
iter != pages.end();
|
||||||
{
|
++iter) {
|
||||||
// Attach two token filters to each page of this file.
|
// Attach two token filters to each page of this file.
|
||||||
// When the file is written, or when the pages' contents
|
// When the file is written, or when the pages' contents
|
||||||
// are retrieved in any other way, the filters will be
|
// are retrieved in any other way, the filters will be
|
||||||
@ -222,11 +214,9 @@ int main(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPDFWriter w(pdf, outfilename);
|
QPDFWriter w(pdf, outfilename);
|
||||||
w.setStaticID(true); // for testing only
|
w.setStaticID(true); // for testing only
|
||||||
w.write();
|
w.write();
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
#include <iostream>
|
#include <qpdf/Buffer.hh>
|
||||||
#include <string.h>
|
#include <qpdf/QIntC.hh>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf [in-password]"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
@ -35,8 +36,8 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
|
|||||||
virtual ~ImageInverter()
|
virtual ~ImageInverter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual void provideStreamData(int objid, int generation,
|
virtual void
|
||||||
Pipeline* pipeline) override;
|
provideStreamData(int objid, int generation, Pipeline* pipeline) override;
|
||||||
|
|
||||||
void registerImage(
|
void registerImage(
|
||||||
QPDFObjectHandle image,
|
QPDFObjectHandle image,
|
||||||
@ -64,8 +65,7 @@ ImageInverter::registerImage(
|
|||||||
// generation number. Recall that a single image object may be
|
// generation number. Recall that a single image object may be
|
||||||
// used more than once, so no need to update the same stream
|
// used more than once, so no need to update the same stream
|
||||||
// multiple times.
|
// multiple times.
|
||||||
if (this->copied_images.count(og) > 0)
|
if (this->copied_images.count(og) > 0) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->copied_images[og] = image.copyStream();
|
this->copied_images[og] = image.copyStream();
|
||||||
@ -79,14 +79,12 @@ ImageInverter::registerImage(
|
|||||||
// filterable in the input QPDF object, so we don't have to deal
|
// filterable in the input QPDF object, so we don't have to deal
|
||||||
// with it explicitly here. We could explicitly use /DCTDecode and
|
// with it explicitly here. We could explicitly use /DCTDecode and
|
||||||
// write through a DCT filter if we wanted.
|
// write through a DCT filter if we wanted.
|
||||||
image.replaceStreamData(self,
|
image.replaceStreamData(
|
||||||
QPDFObjectHandle::newNull(),
|
self, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull());
|
||||||
QPDFObjectHandle::newNull());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageInverter::provideStreamData(int objid, int generation,
|
ImageInverter::provideStreamData(int objid, int generation, Pipeline* pipeline)
|
||||||
Pipeline* pipeline)
|
|
||||||
{
|
{
|
||||||
// Use the object and generation number supplied to look up the
|
// Use the object and generation number supplied to look up the
|
||||||
// image data. Then invert the image data and write the inverted
|
// image data. Then invert the image data and write the inverted
|
||||||
@ -97,29 +95,27 @@ ImageInverter::provideStreamData(int objid, int generation,
|
|||||||
size_t size = data->getSize();
|
size_t size = data->getSize();
|
||||||
unsigned char* buf = data->getBuffer();
|
unsigned char* buf = data->getBuffer();
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
for (size_t i = 0; i < size; ++i)
|
for (size_t i = 0; i < size; ++i) {
|
||||||
{
|
|
||||||
ch = QIntC::to_uchar(0xff - buf[i]);
|
ch = QIntC::to_uchar(0xff - buf[i]);
|
||||||
pipeline->write(&ch, 1);
|
pipeline->write(&ch, 1);
|
||||||
}
|
}
|
||||||
pipeline->finish();
|
pipeline->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
// For test suite
|
// For test suite
|
||||||
bool static_id = false;
|
bool static_id = false;
|
||||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0)) {
|
||||||
{
|
|
||||||
static_id = true;
|
static_id = true;
|
||||||
--argc;
|
--argc;
|
||||||
++argv;
|
++argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! ((argc == 3) || (argc == 4)))
|
if (!((argc == 3) || (argc == 4))) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +123,7 @@ int main(int argc, char* argv[])
|
|||||||
char const* outfilename = argv[2];
|
char const* outfilename = argv[2];
|
||||||
char const* password = (argc == 4) ? argv[3] : "";
|
char const* password = (argc == 4) ? argv[3] : "";
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF qpdf;
|
QPDF qpdf;
|
||||||
qpdf.processFile(infilename, password);
|
qpdf.processFile(infilename, password);
|
||||||
|
|
||||||
@ -139,18 +134,15 @@ int main(int argc, char* argv[])
|
|||||||
std::vector<QPDFPageObjectHelper> pages =
|
std::vector<QPDFPageObjectHelper> pages =
|
||||||
QPDFPageDocumentHelper(qpdf).getAllPages();
|
QPDFPageDocumentHelper(qpdf).getAllPages();
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||||
iter != pages.end(); ++iter)
|
iter != pages.end();
|
||||||
{
|
++iter) {
|
||||||
QPDFPageObjectHelper& page(*iter);
|
QPDFPageObjectHelper& page(*iter);
|
||||||
// Get all images on the page.
|
// Get all images on the page.
|
||||||
std::map<std::string, QPDFObjectHandle> images =
|
std::map<std::string, QPDFObjectHandle> images = page.getImages();
|
||||||
page.getImages();
|
for (auto& iter2 : images) {
|
||||||
for (auto& iter2: images)
|
|
||||||
{
|
|
||||||
QPDFObjectHandle& image = iter2.second;
|
QPDFObjectHandle& image = iter2.second;
|
||||||
QPDFObjectHandle image_dict = image.getDict();
|
QPDFObjectHandle image_dict = image.getDict();
|
||||||
QPDFObjectHandle color_space =
|
QPDFObjectHandle color_space = image_dict.getKey("/ColorSpace");
|
||||||
image_dict.getKey("/ColorSpace");
|
|
||||||
QPDFObjectHandle bits_per_component =
|
QPDFObjectHandle bits_per_component =
|
||||||
image_dict.getKey("/BitsPerComponent");
|
image_dict.getKey("/BitsPerComponent");
|
||||||
|
|
||||||
@ -159,12 +151,10 @@ int main(int argc, char* argv[])
|
|||||||
// pipeStreamData with a null pipeline to determine
|
// pipeStreamData with a null pipeline to determine
|
||||||
// whether the image is filterable. Directly inspect
|
// whether the image is filterable. Directly inspect
|
||||||
// keys to determine the image type.
|
// keys to determine the image type.
|
||||||
if (image.pipeStreamData(0, qpdf_ef_compress,
|
if (image.pipeStreamData(0, qpdf_ef_compress, qpdf_dl_all) &&
|
||||||
qpdf_dl_all) &&
|
|
||||||
color_space.isNameAndEquals("/DeviceGray") &&
|
color_space.isNameAndEquals("/DeviceGray") &&
|
||||||
bits_per_component.isInteger() &&
|
bits_per_component.isInteger() &&
|
||||||
(bits_per_component.getIntValue() == 8))
|
(bits_per_component.getIntValue() == 8)) {
|
||||||
{
|
|
||||||
inv->registerImage(image, p);
|
inv->registerImage(image, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,8 +162,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Write out a new file
|
// Write out a new file
|
||||||
QPDFWriter w(qpdf, outfilename);
|
QPDFWriter w(qpdf, outfilename);
|
||||||
if (static_id)
|
if (static_id) {
|
||||||
{
|
|
||||||
// For the test suite, uncompress streams and use static
|
// For the test suite, uncompress streams and use static
|
||||||
// IDs.
|
// IDs.
|
||||||
w.setStaticID(true); // for testing only
|
w.setStaticID(true); // for testing only
|
||||||
@ -181,9 +170,7 @@ int main(int argc, char* argv[])
|
|||||||
w.write();
|
w.write();
|
||||||
std::cout << whoami << ": new file written to " << outfilename
|
std::cout << whoami << ": new file written to " << outfilename
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << " processing file " << infilename << ": "
|
std::cerr << whoami << " processing file " << infilename << ": "
|
||||||
<< e.what() << std::endl;
|
<< e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -9,18 +9,21 @@
|
|||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
static void usage()
|
static void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s infile infile-password outfile\n", whoami);
|
fprintf(stderr, "Usage: %s infile infile-password outfile\n", whoami);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_progress(int percent, void* data)
|
static void
|
||||||
|
write_progress(int percent, void* data)
|
||||||
{
|
{
|
||||||
printf("%s progress: %d%%\n", (char const*)(data), percent);
|
printf("%s progress: %d%%\n", (char const*)(data), percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
char* infile = NULL;
|
char* infile = NULL;
|
||||||
char* password = NULL;
|
char* password = NULL;
|
||||||
@ -30,21 +33,15 @@ int main(int argc, char* argv[])
|
|||||||
int errors = 0;
|
int errors = 0;
|
||||||
char* p = 0;
|
char* p = 0;
|
||||||
|
|
||||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
if ((p = strrchr(argv[0], '/')) != NULL) {
|
||||||
{
|
|
||||||
whoami = p + 1;
|
whoami = p + 1;
|
||||||
}
|
} else if ((p = strrchr(argv[0], '\\')) != NULL) {
|
||||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
|
||||||
{
|
|
||||||
whoami = p + 1;
|
whoami = p + 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
whoami = argv[0];
|
whoami = argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 4)
|
if (argc != 4) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,8 +50,7 @@ int main(int argc, char* argv[])
|
|||||||
outfile = argv[3];
|
outfile = argv[3];
|
||||||
|
|
||||||
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
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
|
/* Use static ID for testing only. For production, a
|
||||||
* non-static ID is used. See also
|
* non-static ID is used. See also
|
||||||
* qpdf_set_deterministic_ID. */
|
* qpdf_set_deterministic_ID. */
|
||||||
@ -63,25 +59,22 @@ int main(int argc, char* argv[])
|
|||||||
qpdf_register_progress_reporter(qpdf, write_progress, infile);
|
qpdf_register_progress_reporter(qpdf, write_progress, infile);
|
||||||
qpdf_write(qpdf);
|
qpdf_write(qpdf);
|
||||||
}
|
}
|
||||||
while (qpdf_more_warnings(qpdf))
|
while (qpdf_more_warnings(qpdf)) {
|
||||||
{
|
|
||||||
warnings = 1;
|
warnings = 1;
|
||||||
printf("warning: %s\n",
|
printf(
|
||||||
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
"warning: %s\n",
|
||||||
|
qpdf_get_error_full_text(qpdf, qpdf_next_warning(qpdf)));
|
||||||
}
|
}
|
||||||
if (qpdf_has_error(qpdf))
|
if (qpdf_has_error(qpdf)) {
|
||||||
{
|
|
||||||
errors = 1;
|
errors = 1;
|
||||||
printf("error: %s\n",
|
printf(
|
||||||
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
"error: %s\n",
|
||||||
|
qpdf_get_error_full_text(qpdf, qpdf_get_error(qpdf)));
|
||||||
}
|
}
|
||||||
qpdf_cleanup(&qpdf);
|
qpdf_cleanup(&qpdf);
|
||||||
if (errors)
|
if (errors) {
|
||||||
{
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
} else if (warnings) {
|
||||||
else if (warnings)
|
|
||||||
{
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,49 +1,43 @@
|
|||||||
// Author: Vitaliy Pavlyuk
|
// Author: Vitaliy Pavlyuk
|
||||||
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QTC.hh>
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static char const* version = "1.1";
|
static char const* version = "1.1";
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr
|
std::cerr << "Usage: " << whoami
|
||||||
<< "Usage: " << whoami
|
<< " --in in_file [--out out_file] [--key key [--val val]?]+\n"
|
||||||
<< " --in in_file [--out out_file] [--key key [--val val]?]+\n"
|
<< "Modifies/Adds/Removes PDF /Info entries in the in_file\n"
|
||||||
<< "Modifies/Adds/Removes PDF /Info entries in the in_file\n"
|
<< "and stores the result in out_file\n"
|
||||||
<< "and stores the result in out_file\n"
|
<< "Special mode: " << whoami << " --dump file\n"
|
||||||
<< "Special mode: " << whoami << " --dump file\n"
|
<< "dumps all /Info entries to stdout\n";
|
||||||
<< "dumps all /Info entries to stdout\n";
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpInfoDict(QPDF& pdf,
|
void
|
||||||
std::ostream& os = std::cout,
|
dumpInfoDict(
|
||||||
std::string const& sep = ":\t")
|
QPDF& pdf, std::ostream& os = std::cout, std::string const& sep = ":\t")
|
||||||
{
|
{
|
||||||
QPDFObjectHandle trailer = pdf.getTrailer();
|
QPDFObjectHandle trailer = pdf.getTrailer();
|
||||||
if (trailer.hasKey("/Info"))
|
if (trailer.hasKey("/Info")) {
|
||||||
{
|
for (auto& it : trailer.getKey("/Info").ditems()) {
|
||||||
for (auto& it: trailer.getKey("/Info").ditems())
|
|
||||||
{
|
|
||||||
std::string val;
|
std::string val;
|
||||||
if (it.second.isString())
|
if (it.second.isString()) {
|
||||||
{
|
|
||||||
val = it.second.getStringValue();
|
val = it.second.getStringValue();
|
||||||
}
|
} else if (it.second.isName()) {
|
||||||
else if (it.second.isName())
|
|
||||||
{
|
|
||||||
val = it.second.getName();
|
val = it.second.getName();
|
||||||
}
|
} else // according to PDF Spec 1.5, shouldn't happen
|
||||||
else // according to PDF Spec 1.5, shouldn't happen
|
|
||||||
{
|
{
|
||||||
val = it.second.unparseResolved();
|
val = it.second.unparseResolved();
|
||||||
}
|
}
|
||||||
@ -52,36 +46,32 @@ void dumpInfoDict(QPDF& pdf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdfDumpInfoDict(char const* fname)
|
void
|
||||||
|
pdfDumpInfoDict(char const* fname)
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
pdf.processFile(fname);
|
pdf.processFile(fname);
|
||||||
dumpInfoDict(pdf);
|
dumpInfoDict(pdf);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
|
||||||
bool static_id = false;
|
bool static_id = false;
|
||||||
std::map<std::string, std::string> Keys;
|
std::map<std::string, std::string> Keys;
|
||||||
|
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if ((argc == 2) && (! strcmp(argv[1], "--version")) )
|
if ((argc == 2) && (!strcmp(argv[1], "--version"))) {
|
||||||
{
|
|
||||||
std::cout << whoami << " version " << version << std::endl;
|
std::cout << whoami << " version " << version << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
if ((argc == 3) && (! strcmp(argv[1], "--dump")))
|
if ((argc == 3) && (!strcmp(argv[1], "--dump"))) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info --dump");
|
QTC::TC("examples", "pdf-mod-info --dump");
|
||||||
pdfDumpInfoDict(argv[2]);
|
pdfDumpInfoDict(argv[2]);
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -91,59 +81,43 @@ int main(int argc, char* argv[])
|
|||||||
char* fl_out = 0;
|
char* fl_out = 0;
|
||||||
std::string cur_key;
|
std::string cur_key;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i) {
|
||||||
{
|
if ((!strcmp(argv[i], "--in")) && (++i < argc)) {
|
||||||
if ((! strcmp(argv[i], "--in")) && (++i < argc))
|
|
||||||
{
|
|
||||||
fl_in = argv[i];
|
fl_in = argv[i];
|
||||||
}
|
} else if ((!strcmp(argv[i], "--out")) && (++i < argc)) {
|
||||||
else if ((! strcmp(argv[i], "--out")) && (++i < argc))
|
|
||||||
{
|
|
||||||
fl_out = argv[i];
|
fl_out = argv[i];
|
||||||
}
|
} else if (!strcmp(argv[i], "--static-id")) // don't document
|
||||||
else if (! strcmp(argv[i], "--static-id")) // don't document
|
|
||||||
{
|
{
|
||||||
static_id = true; // this should be used in test suites only
|
static_id = true; // this should be used in test suites only
|
||||||
}
|
} else if ((!strcmp(argv[i], "--key")) && (++i < argc)) {
|
||||||
else if ((! strcmp(argv[i], "--key")) && (++i < argc))
|
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info -key");
|
QTC::TC("examples", "pdf-mod-info -key");
|
||||||
cur_key = argv[i];
|
cur_key = argv[i];
|
||||||
if (! ((cur_key.length() > 0) && (cur_key.at(0) == '/')))
|
if (!((cur_key.length() > 0) && (cur_key.at(0) == '/'))) {
|
||||||
{
|
|
||||||
cur_key = "/" + cur_key;
|
cur_key = "/" + cur_key;
|
||||||
}
|
}
|
||||||
Keys[cur_key] = "";
|
Keys[cur_key] = "";
|
||||||
}
|
} else if ((!strcmp(argv[i], "--val")) && (++i < argc)) {
|
||||||
else if ((! strcmp(argv[i], "--val")) && (++i < argc))
|
if (cur_key.empty()) {
|
||||||
{
|
|
||||||
if (cur_key.empty())
|
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info usage wrong val");
|
QTC::TC("examples", "pdf-mod-info usage wrong val");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
QTC::TC("examples", "pdf-mod-info -val");
|
QTC::TC("examples", "pdf-mod-info -val");
|
||||||
Keys[cur_key] = argv[i];
|
Keys[cur_key] = argv[i];
|
||||||
cur_key.clear();
|
cur_key.clear();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info usage junk");
|
QTC::TC("examples", "pdf-mod-info usage junk");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! fl_in)
|
if (!fl_in) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info no in file");
|
QTC::TC("examples", "pdf-mod-info no in file");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
if (! fl_out)
|
if (!fl_out) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info in-place");
|
QTC::TC("examples", "pdf-mod-info in-place");
|
||||||
fl_out = fl_in;
|
fl_out = fl_in;
|
||||||
}
|
}
|
||||||
if (Keys.size() == 0)
|
if (Keys.size() == 0) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info no keys");
|
QTC::TC("examples", "pdf-mod-info no keys");
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
@ -151,8 +125,7 @@ int main(int argc, char* argv[])
|
|||||||
std::string fl_tmp = fl_out;
|
std::string fl_tmp = fl_out;
|
||||||
fl_tmp += ".tmp";
|
fl_tmp += ".tmp";
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF file;
|
QPDF file;
|
||||||
file.processFile(fl_in);
|
file.processFile(fl_in);
|
||||||
|
|
||||||
@ -160,28 +133,22 @@ int main(int argc, char* argv[])
|
|||||||
QPDFObjectHandle fileinfo;
|
QPDFObjectHandle fileinfo;
|
||||||
|
|
||||||
for (std::map<std::string, std::string>::const_iterator it =
|
for (std::map<std::string, std::string>::const_iterator it =
|
||||||
Keys.begin(); Keys.end() != it; ++it)
|
Keys.begin();
|
||||||
{
|
Keys.end() != it;
|
||||||
if (! fileinfo.isInitialized())
|
++it) {
|
||||||
{
|
if (!fileinfo.isInitialized()) {
|
||||||
if (filetrailer.hasKey("/Info"))
|
if (filetrailer.hasKey("/Info")) {
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info has info");
|
QTC::TC("examples", "pdf-mod-info has info");
|
||||||
fileinfo = filetrailer.getKey("/Info");
|
fileinfo = filetrailer.getKey("/Info");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("examples", "pdf-mod-info file no info");
|
QTC::TC("examples", "pdf-mod-info file no info");
|
||||||
fileinfo = QPDFObjectHandle::newDictionary();
|
fileinfo = QPDFObjectHandle::newDictionary();
|
||||||
filetrailer.replaceKey("/Info", fileinfo);
|
filetrailer.replaceKey("/Info", fileinfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (it->second == "")
|
if (it->second == "") {
|
||||||
{
|
|
||||||
fileinfo.removeKey(it->first);
|
fileinfo.removeKey(it->first);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QPDFObjectHandle elt = fileinfo.newString(it->second);
|
QPDFObjectHandle elt = fileinfo.newString(it->second);
|
||||||
elt.makeDirect();
|
elt.makeDirect();
|
||||||
fileinfo.replaceKey(it->first, elt);
|
fileinfo.replaceKey(it->first, elt);
|
||||||
@ -192,21 +159,17 @@ int main(int argc, char* argv[])
|
|||||||
w.setLinearization(true);
|
w.setLinearization(true);
|
||||||
w.setStaticID(static_id); // for testing only
|
w.setStaticID(static_id); // for testing only
|
||||||
w.write();
|
w.write();
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
(void)remove(fl_out);
|
||||||
(void) remove(fl_out);
|
QUtil::os_wrapper(
|
||||||
QUtil::os_wrapper("rename " + fl_tmp + " " + std::string(fl_out),
|
"rename " + fl_tmp + " " + std::string(fl_out),
|
||||||
rename(fl_tmp.c_str(), fl_out));
|
rename(fl_tmp.c_str(), fl_out));
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -3,26 +3,26 @@
|
|||||||
#include <qpdf/QPDFNumberTreeObjectHelper.hh>
|
#include <qpdf/QPDFNumberTreeObjectHelper.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " outfile.pdf"
|
std::cerr << "Usage: " << whoami << " outfile.pdf" << std::endl
|
||||||
<< std::endl
|
|
||||||
<< "Create some name/number trees and write to a file"
|
<< "Create some name/number trees and write to a file"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,8 +62,8 @@ int main(int argc, char* argv[])
|
|||||||
name_tree.insert("R", QPDFObjectHandle::newUnicodeString("rook"));
|
name_tree.insert("R", QPDFObjectHandle::newUnicodeString("rook"));
|
||||||
name_tree.insert("B", QPDFObjectHandle::newUnicodeString("bishop"));
|
name_tree.insert("B", QPDFObjectHandle::newUnicodeString("bishop"));
|
||||||
name_tree.insert("N", QPDFObjectHandle::newUnicodeString("knight"));
|
name_tree.insert("N", QPDFObjectHandle::newUnicodeString("knight"));
|
||||||
auto iter = name_tree.insert(
|
auto iter =
|
||||||
"P", QPDFObjectHandle::newUnicodeString("pawn"));
|
name_tree.insert("P", QPDFObjectHandle::newUnicodeString("pawn"));
|
||||||
// Look at the iterator
|
// Look at the iterator
|
||||||
std::cout << "just inserted " << iter->first << " -> "
|
std::cout << "just inserted " << iter->first << " -> "
|
||||||
<< iter->second.unparse() << std::endl;
|
<< iter->second.unparse() << std::endl;
|
||||||
@ -77,28 +77,24 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Use range-for iteration
|
// Use range-for iteration
|
||||||
std::cout << "Name tree items:" << std::endl;
|
std::cout << "Name tree items:" << std::endl;
|
||||||
for (auto i: name_tree)
|
for (auto i : name_tree) {
|
||||||
{
|
std::cout << " " << i.first << " -> " << i.second.unparse()
|
||||||
std::cout << " " << i.first << " -> "
|
<< std::endl;
|
||||||
<< i.second.unparse() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a small tree, so everything will be at the root. We can
|
// This is a small tree, so everything will be at the root. We can
|
||||||
// look at it using dictionary and array iterators.
|
// look at it using dictionary and array iterators.
|
||||||
std::cout << "Keys in name tree object:" << std::endl;
|
std::cout << "Keys in name tree object:" << std::endl;
|
||||||
QPDFObjectHandle names;
|
QPDFObjectHandle names;
|
||||||
for (auto const& i: name_tree_oh.ditems())
|
for (auto const& i : name_tree_oh.ditems()) {
|
||||||
{
|
|
||||||
std::cout << i.first << std::endl;
|
std::cout << i.first << std::endl;
|
||||||
if (i.first == "/Names")
|
if (i.first == "/Names") {
|
||||||
{
|
|
||||||
names = i.second;
|
names = i.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Values in names array:
|
// Values in names array:
|
||||||
std::cout << "Values in names:" << std::endl;
|
std::cout << "Values in names:" << std::endl;
|
||||||
for (auto& i: names.aitems())
|
for (auto& i : names.aitems()) {
|
||||||
{
|
|
||||||
std::cout << " " << i.unparse() << std::endl;
|
std::cout << " " << i.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,8 +108,8 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// 10.2 API
|
// 10.2 API
|
||||||
iter = name_tree.find("Q");
|
iter = name_tree.find("Q");
|
||||||
std::cout << "Q: " << iter->first << " -> "
|
std::cout << "Q: " << iter->first << " -> " << iter->second.unparse()
|
||||||
<< iter->second.unparse() << std::endl;
|
<< std::endl;
|
||||||
iter = name_tree.find("W");
|
iter = name_tree.find("W");
|
||||||
std::cout << "W found: " << (iter != name_tree.end()) << std::endl;
|
std::cout << "W found: " << (iter != name_tree.end()) << std::endl;
|
||||||
// Allow find to return predecessor
|
// Allow find to return predecessor
|
||||||
@ -146,22 +142,18 @@ int main(int argc, char* argv[])
|
|||||||
auto number_tree_oh = number_tree.getObjectHandle();
|
auto number_tree_oh = number_tree.getObjectHandle();
|
||||||
example.replaceKey("/NumberTree", number_tree_oh);
|
example.replaceKey("/NumberTree", number_tree_oh);
|
||||||
auto iter2 = number_tree.begin();
|
auto iter2 = number_tree.begin();
|
||||||
for (int i = 7; i <= 350; i += 7)
|
for (int i = 7; i <= 350; i += 7) {
|
||||||
{
|
iter2.insertAfter(
|
||||||
iter2.insertAfter(i, QPDFObjectHandle::newString(
|
i,
|
||||||
"-" + QUtil::int_to_string(i) + "-"));
|
QPDFObjectHandle::newString("-" + QUtil::int_to_string(i) + "-"));
|
||||||
}
|
}
|
||||||
std::cout << "Numbers:" << std::endl;
|
std::cout << "Numbers:" << std::endl;
|
||||||
int n = 1;
|
int n = 1;
|
||||||
for (auto& i: number_tree)
|
for (auto& i : number_tree) {
|
||||||
{
|
|
||||||
std::cout << i.first << " -> " << i.second.getUTF8Value();
|
std::cout << i.first << " -> " << i.second.getUTF8Value();
|
||||||
if (n % 5)
|
if (n % 5) {
|
||||||
{
|
|
||||||
std::cout << ", ";
|
std::cout << ", ";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
@ -171,28 +163,20 @@ int main(int argc, char* argv[])
|
|||||||
// advances. This makes it possible to filter while iterating.
|
// advances. This makes it possible to filter while iterating.
|
||||||
// Remove all items that are multiples of 5.
|
// Remove all items that are multiples of 5.
|
||||||
iter2 = number_tree.begin();
|
iter2 = number_tree.begin();
|
||||||
while (iter2 != number_tree.end())
|
while (iter2 != number_tree.end()) {
|
||||||
{
|
if (iter2->first % 5 == 0) {
|
||||||
if (iter2->first % 5 == 0)
|
iter2.remove(); // also advances
|
||||||
{
|
} else {
|
||||||
iter2.remove(); // also advances
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++iter2;
|
++iter2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "Numbers after filtering:" << std::endl;
|
std::cout << "Numbers after filtering:" << std::endl;
|
||||||
n = 1;
|
n = 1;
|
||||||
for (auto& i: number_tree)
|
for (auto& i : number_tree) {
|
||||||
{
|
|
||||||
std::cout << i.first << " -> " << i.second.getUTF8Value();
|
std::cout << i.first << " -> " << i.second.getUTF8Value();
|
||||||
if (n % 5)
|
if (n % 5) {
|
||||||
{
|
|
||||||
std::cout << ", ";
|
std::cout << ", ";
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
++n;
|
++n;
|
||||||
|
@ -1,46 +1,43 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " filename" << std::endl
|
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);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if ((argc == 2) && (strcmp(argv[1], "--version") == 0))
|
if ((argc == 2) && (strcmp(argv[1], "--version") == 0)) {
|
||||||
{
|
|
||||||
std::cout << whoami << " version 1.3" << std::endl;
|
std::cout << whoami << " version 1.3" << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc != 2) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
char const* filename = argv[1];
|
char const* filename = argv[1];
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
pdf.processFile(filename);
|
pdf.processFile(filename);
|
||||||
QPDFObjectHandle root = pdf.getRoot();
|
QPDFObjectHandle root = pdf.getRoot();
|
||||||
QPDFObjectHandle pages = root.getKey("/Pages");
|
QPDFObjectHandle pages = root.getKey("/Pages");
|
||||||
QPDFObjectHandle count = pages.getKey("/Count");
|
QPDFObjectHandle count = pages.getKey("/Count");
|
||||||
std::cout << count.getIntValue() << std::endl;
|
std::cout << count.getIntValue() << std::endl;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
// This program demonstrates use of form XObjects to overlay a page
|
// This program demonstrates use of form XObjects to overlay a page
|
||||||
// from one file onto all pages of another file. The qpdf program's
|
// from one file onto all pages of another file. The qpdf program's
|
||||||
@ -14,19 +14,17 @@
|
|||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile pagefile outfile"
|
std::cerr << "Usage: " << whoami << " infile pagefile outfile" << std::endl
|
||||||
<< std::endl
|
|
||||||
<< "Stamp page 1 of pagefile on every page of infile,"
|
<< "Stamp page 1 of pagefile on every page of infile,"
|
||||||
<< " writing to outfile"
|
<< " writing to outfile" << std::endl;
|
||||||
<< std::endl;
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stamp_page(char const* infile,
|
static void
|
||||||
char const* stampfile,
|
stamp_page(char const* infile, char const* stampfile, char const* outfile)
|
||||||
char const* outfile)
|
|
||||||
{
|
{
|
||||||
QPDF inpdf;
|
QPDF inpdf;
|
||||||
inpdf.processFile(infile);
|
inpdf.processFile(infile);
|
||||||
@ -45,8 +43,8 @@ static void stamp_page(char const* infile,
|
|||||||
std::vector<QPDFPageObjectHelper> pages =
|
std::vector<QPDFPageObjectHelper> pages =
|
||||||
QPDFPageDocumentHelper(inpdf).getAllPages();
|
QPDFPageDocumentHelper(inpdf).getAllPages();
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||||
iter != pages.end(); ++iter)
|
iter != pages.end();
|
||||||
{
|
++iter) {
|
||||||
QPDFPageObjectHelper& ph = *iter;
|
QPDFPageObjectHelper& ph = *iter;
|
||||||
|
|
||||||
// Find a unique resource name for the new form XObject
|
// Find a unique resource name for the new form XObject
|
||||||
@ -57,11 +55,9 @@ static void stamp_page(char const* infile,
|
|||||||
// Generate content to place the form XObject centered within
|
// Generate content to place the form XObject centered within
|
||||||
// destination page's trim box.
|
// destination page's trim box.
|
||||||
QPDFMatrix m;
|
QPDFMatrix m;
|
||||||
std::string content =
|
std::string content = ph.placeFormXObject(
|
||||||
ph.placeFormXObject(
|
stamp_fo, name, ph.getTrimBox().getArrayAsRectangle(), m);
|
||||||
stamp_fo, name, ph.getTrimBox().getArrayAsRectangle(), m);
|
if (!content.empty()) {
|
||||||
if (! content.empty())
|
|
||||||
{
|
|
||||||
// Append the content to the page's content. Surround the
|
// Append the content to the page's content. Surround the
|
||||||
// original content with q...Q to the new content from the
|
// original content with q...Q to the new content from the
|
||||||
// page's original content.
|
// page's original content.
|
||||||
@ -80,28 +76,25 @@ static void stamp_page(char const* infile,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPDFWriter w(inpdf, outfile);
|
QPDFWriter w(inpdf, outfile);
|
||||||
w.setStaticID(true); // for testing only
|
w.setStaticID(true); // for testing only
|
||||||
w.write();
|
w.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 4)
|
if (argc != 4) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
char const* infile = argv[1];
|
char const* infile = argv[1];
|
||||||
char const* stampfile = argv[2];
|
char const* stampfile = argv[2];
|
||||||
char const* outfile = argv[3];
|
char const* outfile = argv[3];
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
stamp_page(infile, stampfile, outfile);
|
stamp_page(infile, stampfile, outfile);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/QIntC.hh>
|
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " filename page-number" << std::endl
|
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"
|
||||||
@ -38,17 +39,14 @@ ParserCallbacks::contentSize(size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ParserCallbacks::handleObject(QPDFObjectHandle obj,
|
ParserCallbacks::handleObject(
|
||||||
size_t offset, size_t length)
|
QPDFObjectHandle obj, size_t offset, size_t length)
|
||||||
{
|
{
|
||||||
std::cout << obj.getTypeName() << ", offset=" << offset
|
std::cout << obj.getTypeName() << ", offset=" << offset
|
||||||
<< ", length=" << length << ": ";
|
<< ", length=" << length << ": ";
|
||||||
if (obj.isInlineImage())
|
if (obj.isInlineImage()) {
|
||||||
{
|
|
||||||
std::cout << QUtil::hex_encode(obj.getInlineImageValue()) << std::endl;
|
std::cout << QUtil::hex_encode(obj.getInlineImageValue()) << std::endl;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << obj.unparse() << std::endl;
|
std::cout << obj.unparse() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,34 +57,30 @@ ParserCallbacks::handleEOF()
|
|||||||
std::cout << "-EOF-" << std::endl;
|
std::cout << "-EOF-" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 3) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
char const* filename = argv[1];
|
char const* filename = argv[1];
|
||||||
int pageno = QUtil::string_to_int(argv[2]);
|
int pageno = QUtil::string_to_int(argv[2]);
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF pdf;
|
QPDF pdf;
|
||||||
pdf.processFile(filename);
|
pdf.processFile(filename);
|
||||||
std::vector<QPDFPageObjectHelper> pages =
|
std::vector<QPDFPageObjectHelper> pages =
|
||||||
QPDFPageDocumentHelper(pdf).getAllPages();
|
QPDFPageDocumentHelper(pdf).getAllPages();
|
||||||
if ((pageno < 1) || (QIntC::to_size(pageno) > pages.size()))
|
if ((pageno < 1) || (QIntC::to_size(pageno) > pages.size())) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFPageObjectHelper& page = pages.at(QIntC::to_size(pageno-1));
|
QPDFPageObjectHelper& page = pages.at(QIntC::to_size(pageno - 1));
|
||||||
ParserCallbacks cb;
|
ParserCallbacks cb;
|
||||||
page.parseContents(&cb);
|
page.parseContents(&cb);
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": " << e.what() << std::endl;
|
std::cerr << whoami << ": " << e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
|
||||||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||||
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
void usage()
|
void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf value"
|
std::cerr << "Usage: " << whoami << " infile.pdf outfile.pdf value"
|
||||||
<< std::endl
|
<< std::endl
|
||||||
@ -19,13 +20,12 @@ void usage()
|
|||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
int main(int argc, char* argv[])
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 4)
|
if (argc != 4) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,8 +39,7 @@ int main(int argc, char* argv[])
|
|||||||
// to illustrate use of the helper classes around interactive
|
// to illustrate use of the helper classes around interactive
|
||||||
// forms.
|
// forms.
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
QPDF qpdf;
|
QPDF qpdf;
|
||||||
qpdf.processFile(infilename);
|
qpdf.processFile(infilename);
|
||||||
|
|
||||||
@ -55,8 +54,8 @@ int main(int argc, char* argv[])
|
|||||||
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
|
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator page_iter =
|
for (std::vector<QPDFPageObjectHelper>::iterator page_iter =
|
||||||
pages.begin();
|
pages.begin();
|
||||||
page_iter != pages.end(); ++page_iter)
|
page_iter != pages.end();
|
||||||
{
|
++page_iter) {
|
||||||
// Get all widget annotations for each page. Widget
|
// Get all widget annotations for each page. Widget
|
||||||
// annotations are the ones that contain the details of
|
// annotations are the ones that contain the details of
|
||||||
// what's in a form field.
|
// what's in a form field.
|
||||||
@ -64,14 +63,13 @@ int main(int argc, char* argv[])
|
|||||||
afdh.getWidgetAnnotationsForPage(*page_iter);
|
afdh.getWidgetAnnotationsForPage(*page_iter);
|
||||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter =
|
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter =
|
||||||
annotations.begin();
|
annotations.begin();
|
||||||
annot_iter != annotations.end(); ++annot_iter)
|
annot_iter != annotations.end();
|
||||||
{
|
++annot_iter) {
|
||||||
// For each annotation, find its associated field. If
|
// For each annotation, find its associated field. If
|
||||||
// it's a text field, set its value.
|
// it's a text field, set its value.
|
||||||
QPDFFormFieldObjectHelper ffh =
|
QPDFFormFieldObjectHelper ffh =
|
||||||
afdh.getFieldForAnnotation(*annot_iter);
|
afdh.getFieldForAnnotation(*annot_iter);
|
||||||
if (ffh.getFieldType() == "/Tx")
|
if (ffh.getFieldType() == "/Tx") {
|
||||||
{
|
|
||||||
// Set the value. Passing false as the second
|
// Set the value. Passing false as the second
|
||||||
// value prevents qpdf from setting
|
// value prevents qpdf from setting
|
||||||
// /NeedAppearances to true (but will not turn it
|
// /NeedAppearances to true (but will not turn it
|
||||||
@ -92,9 +90,7 @@ int main(int argc, char* argv[])
|
|||||||
QPDFWriter w(qpdf, outfilename);
|
QPDFWriter w(qpdf, outfilename);
|
||||||
w.setStaticID(true); // for testing only
|
w.setStaticID(true); // for testing only
|
||||||
w.write();
|
w.write();
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception &e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << " processing file " << infilename << ": "
|
std::cerr << whoami << " processing file " << infilename << ": "
|
||||||
<< e.what() << std::endl;
|
<< e.what() << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -4,22 +4,21 @@
|
|||||||
// does.
|
// does.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/QIntC.hh>
|
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
static bool static_id = false;
|
static bool static_id = false;
|
||||||
|
|
||||||
static void process(char const* whoami,
|
static void
|
||||||
char const* infile,
|
process(char const* whoami, char const* infile, std::string outprefix)
|
||||||
std::string outprefix)
|
|
||||||
{
|
{
|
||||||
QPDF inpdf;
|
QPDF inpdf;
|
||||||
inpdf.processFile(infile);
|
inpdf.processFile(infile);
|
||||||
@ -29,8 +28,8 @@ static void process(char const* whoami,
|
|||||||
QIntC::to_int(QUtil::uint_to_string(pages.size()).length());
|
QIntC::to_int(QUtil::uint_to_string(pages.size()).length());
|
||||||
int pageno = 0;
|
int pageno = 0;
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||||
iter != pages.end(); ++iter)
|
iter != pages.end();
|
||||||
{
|
++iter) {
|
||||||
QPDFPageObjectHelper& page(*iter);
|
QPDFPageObjectHelper& page(*iter);
|
||||||
std::string outfile =
|
std::string outfile =
|
||||||
outprefix + QUtil::int_to_string(++pageno, pageno_len) + ".pdf";
|
outprefix + QUtil::int_to_string(++pageno, pageno_len) + ".pdf";
|
||||||
@ -38,8 +37,7 @@ static void process(char const* whoami,
|
|||||||
outpdf.emptyPDF();
|
outpdf.emptyPDF();
|
||||||
QPDFPageDocumentHelper(outpdf).addPage(page, false);
|
QPDFPageDocumentHelper(outpdf).addPage(page, false);
|
||||||
QPDFWriter outpdfw(outpdf, outfile.c_str());
|
QPDFWriter outpdfw(outpdf, outfile.c_str());
|
||||||
if (static_id)
|
if (static_id) {
|
||||||
{
|
|
||||||
// For the test suite, uncompress streams and use static
|
// For the test suite, uncompress streams and use static
|
||||||
// IDs.
|
// IDs.
|
||||||
outpdfw.setStaticID(true); // for testing only
|
outpdfw.setStaticID(true); // for testing only
|
||||||
@ -49,34 +47,31 @@ static void process(char const* whoami,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(char const* whoami)
|
void
|
||||||
|
usage(char const* whoami)
|
||||||
{
|
{
|
||||||
std::cerr << "Usage: " << whoami << " infile outprefix" << std::endl;
|
std::cerr << "Usage: " << whoami << " infile outprefix" << std::endl;
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
char const* whoami = QUtil::getWhoami(argv[0]);
|
char const* whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
// For test suite
|
// For test suite
|
||||||
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0))
|
if ((argc > 1) && (strcmp(argv[1], " --static-id") == 0)) {
|
||||||
{
|
|
||||||
static_id = true;
|
static_id = true;
|
||||||
--argc;
|
--argc;
|
||||||
++argv;
|
++argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 3) {
|
||||||
{
|
|
||||||
usage(whoami);
|
usage(whoami);
|
||||||
}
|
}
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
process(whoami, argv[1], argv[2]);
|
process(whoami, argv[1], argv[2]);
|
||||||
}
|
} catch (std::exception const& e) {
|
||||||
catch (std::exception const& e)
|
|
||||||
{
|
|
||||||
std::cerr << whoami << ": exception: " << e.what() << std::endl;
|
std::cerr << whoami << ": exception: " << e.what() << std::endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,32 @@
|
|||||||
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDFJob.hh>
|
#include <qpdf/QPDFJob.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/QIntC.hh>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
// This program is a simple demonstration of different ways to use the
|
// This program is a simple demonstration of different ways to use the
|
||||||
// QPDFJob API.
|
// QPDFJob API.
|
||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
static void usage()
|
static void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
std::cerr
|
std::cerr << "Usage: " << whoami << std::endl
|
||||||
<< "Usage: " << whoami << std::endl
|
<< "This program linearizes the first page of in.pdf to out1.pdf,"
|
||||||
<< "This program linearizes the first page of in.pdf to out1.pdf,"
|
<< " out2.pdf, and" << std::endl
|
||||||
<< " out2.pdf, and"
|
<< " out3.pdf, each demonstrating a different way to use the"
|
||||||
<< std::endl
|
<< " QPDFJob API" << std::endl;
|
||||||
<< " out3.pdf, each demonstrating a different way to use the"
|
|
||||||
<< " QPDFJob API"
|
|
||||||
<< std::endl;
|
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
whoami = QUtil::getWhoami(argv[0]);
|
whoami = QUtil::getWhoami(argv[0]);
|
||||||
|
|
||||||
if (argc != 1)
|
if (argc != 1) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,8 +37,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// Note that staticId is used for testing only.
|
// Note that staticId is used for testing only.
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// Use the config API
|
// Use the config API
|
||||||
QPDFJob j;
|
QPDFJob j;
|
||||||
j.config()
|
j.config()
|
||||||
@ -54,15 +51,12 @@ int main(int argc, char* argv[])
|
|||||||
->checkConfiguration();
|
->checkConfiguration();
|
||||||
j.run();
|
j.run();
|
||||||
std::cout << "out1 status: " << j.getExitCode() << std::endl;
|
std::cout << "out1 status: " << j.getExitCode() << std::endl;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "exception: " << e.what() << std::endl;
|
std::cerr << "exception: " << e.what() << std::endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
char const* new_argv[] = {
|
char const* new_argv[] = {
|
||||||
whoami,
|
whoami,
|
||||||
"in.pdf",
|
"in.pdf",
|
||||||
@ -73,21 +67,17 @@ int main(int argc, char* argv[])
|
|||||||
"1",
|
"1",
|
||||||
"--",
|
"--",
|
||||||
"--static-id",
|
"--static-id",
|
||||||
nullptr
|
nullptr};
|
||||||
};
|
|
||||||
QPDFJob j;
|
QPDFJob j;
|
||||||
j.initializeFromArgv(new_argv);
|
j.initializeFromArgv(new_argv);
|
||||||
j.run();
|
j.run();
|
||||||
std::cout << "out2 status: " << j.getExitCode() << std::endl;
|
std::cout << "out2 status: " << j.getExitCode() << std::endl;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "exception: " << e.what() << std::endl;
|
std::cerr << "exception: " << e.what() << std::endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
// Use the JSON API
|
// Use the JSON API
|
||||||
QPDFJob j;
|
QPDFJob j;
|
||||||
j.initializeFromJson(R"({
|
j.initializeFromJson(R"({
|
||||||
@ -105,9 +95,7 @@ int main(int argc, char* argv[])
|
|||||||
)");
|
)");
|
||||||
j.run();
|
j.run();
|
||||||
std::cout << "out3 status: " << j.getExitCode() << std::endl;
|
std::cout << "out3 status: " << j.getExitCode() << std::endl;
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "exception: " << e.what() << std::endl;
|
std::cerr << "exception: " << e.what() << std::endl;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,15 @@
|
|||||||
|
|
||||||
static char const* whoami = 0;
|
static char const* whoami = 0;
|
||||||
|
|
||||||
static void usage()
|
static void
|
||||||
|
usage()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s infile outfile\n", whoami);
|
fprintf(stderr, "Usage: %s infile outfile\n", whoami);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int
|
||||||
|
main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
char* infile = NULL;
|
char* infile = NULL;
|
||||||
char* outfile = NULL;
|
char* outfile = NULL;
|
||||||
@ -24,21 +26,15 @@ int main(int argc, char* argv[])
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
char* p = 0;
|
char* p = 0;
|
||||||
|
|
||||||
if ((p = strrchr(argv[0], '/')) != NULL)
|
if ((p = strrchr(argv[0], '/')) != NULL) {
|
||||||
{
|
|
||||||
whoami = p + 1;
|
whoami = p + 1;
|
||||||
}
|
} else if ((p = strrchr(argv[0], '\\')) != NULL) {
|
||||||
else if ((p = strrchr(argv[0], '\\')) != NULL)
|
|
||||||
{
|
|
||||||
whoami = p + 1;
|
whoami = p + 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
whoami = argv[0];
|
whoami = argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 3) {
|
||||||
{
|
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <qpdf/Pl_Discard.hh>
|
|
||||||
#include <qpdf/Pl_ASCII85Decoder.hh>
|
#include <qpdf/Pl_ASCII85Decoder.hh>
|
||||||
|
#include <qpdf/Pl_Discard.hh>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@ -34,17 +34,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include <qpdf/Pl_Discard.hh>
|
|
||||||
#include <qpdf/Pl_DCT.hh>
|
#include <qpdf/Pl_DCT.hh>
|
||||||
|
#include <qpdf/Pl_Discard.hh>
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
class FuzzHelper
|
class FuzzHelper
|
||||||
{
|
{
|
||||||
@ -35,17 +35,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Used by jpeg library to work around false positives in memory
|
// Used by jpeg library to work around false positives in memory
|
||||||
|
@ -34,17 +34,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <qpdf/Pl_Discard.hh>
|
|
||||||
#include <qpdf/Pl_ASCIIHexDecoder.hh>
|
#include <qpdf/Pl_ASCIIHexDecoder.hh>
|
||||||
|
#include <qpdf/Pl_Discard.hh>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@ -34,17 +34,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -34,17 +34,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -34,17 +34,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -1,22 +1,30 @@
|
|||||||
|
#include <qpdf/Buffer.hh>
|
||||||
|
#include <qpdf/BufferInputSource.hh>
|
||||||
|
#include <qpdf/Pl_Discard.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
|
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
||||||
|
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
||||||
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
||||||
|
#include <qpdf/QPDFPageLabelDocumentHelper.hh>
|
||||||
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/QPDFWriter.hh>
|
#include <qpdf/QPDFWriter.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
#include <qpdf/BufferInputSource.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
|
||||||
#include <qpdf/Pl_Discard.hh>
|
|
||||||
#include <qpdf/QPDFPageDocumentHelper.hh>
|
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFPageLabelDocumentHelper.hh>
|
|
||||||
#include <qpdf/QPDFOutlineDocumentHelper.hh>
|
|
||||||
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
class DiscardContents: public QPDFObjectHandle::ParserCallbacks
|
class DiscardContents: public QPDFObjectHandle::ParserCallbacks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~DiscardContents() {}
|
virtual ~DiscardContents()
|
||||||
virtual void handleObject(QPDFObjectHandle) {}
|
{
|
||||||
virtual void handleEOF() {}
|
}
|
||||||
|
virtual void
|
||||||
|
handleObject(QPDFObjectHandle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual void
|
||||||
|
handleEOF()
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FuzzHelper
|
class FuzzHelper
|
||||||
@ -66,16 +74,11 @@ FuzzHelper::getWriter(PointerHolder<QPDF> qpdf)
|
|||||||
void
|
void
|
||||||
FuzzHelper::doWrite(PointerHolder<QPDFWriter> w)
|
FuzzHelper::doWrite(PointerHolder<QPDFWriter> w)
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
w->write();
|
w->write();
|
||||||
}
|
} catch (QPDFExc const& e) {
|
||||||
catch (QPDFExc const& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,14 +136,12 @@ FuzzHelper::testPages()
|
|||||||
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
|
std::vector<QPDFPageObjectHelper> pages = pdh.getAllPages();
|
||||||
DiscardContents discard_contents;
|
DiscardContents discard_contents;
|
||||||
int pageno = 0;
|
int pageno = 0;
|
||||||
for (std::vector<QPDFPageObjectHelper>::iterator iter =
|
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
|
||||||
pages.begin();
|
iter != pages.end();
|
||||||
iter != pages.end(); ++iter)
|
++iter) {
|
||||||
{
|
|
||||||
QPDFPageObjectHelper& page(*iter);
|
QPDFPageObjectHelper& page(*iter);
|
||||||
++pageno;
|
++pageno;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
page.coalesceContentStreams();
|
page.coalesceContentStreams();
|
||||||
page.parseContents(&discard_contents);
|
page.parseContents(&discard_contents);
|
||||||
page.getImages();
|
page.getImages();
|
||||||
@ -153,16 +154,13 @@ FuzzHelper::testPages()
|
|||||||
afdh.getWidgetAnnotationsForPage(page);
|
afdh.getWidgetAnnotationsForPage(page);
|
||||||
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter =
|
for (std::vector<QPDFAnnotationObjectHelper>::iterator annot_iter =
|
||||||
annotations.begin();
|
annotations.begin();
|
||||||
annot_iter != annotations.end(); ++annot_iter)
|
annot_iter != annotations.end();
|
||||||
{
|
++annot_iter) {
|
||||||
QPDFAnnotationObjectHelper& aoh = *annot_iter;
|
QPDFAnnotationObjectHelper& aoh = *annot_iter;
|
||||||
afdh.getFieldForAnnotation(aoh);
|
afdh.getFieldForAnnotation(aoh);
|
||||||
}
|
}
|
||||||
}
|
} catch (QPDFExc& e) {
|
||||||
catch (QPDFExc& e)
|
std::cerr << "page " << pageno << ": " << e.what() << std::endl;
|
||||||
{
|
|
||||||
std::cerr << "page " << pageno << ": "
|
|
||||||
<< e.what() << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,16 +169,15 @@ void
|
|||||||
FuzzHelper::testOutlines()
|
FuzzHelper::testOutlines()
|
||||||
{
|
{
|
||||||
PointerHolder<QPDF> q = getQpdf();
|
PointerHolder<QPDF> q = getQpdf();
|
||||||
std::list<std::vector<QPDFOutlineObjectHelper> > queue;
|
std::list<std::vector<QPDFOutlineObjectHelper>> queue;
|
||||||
QPDFOutlineDocumentHelper odh(*q);
|
QPDFOutlineDocumentHelper odh(*q);
|
||||||
queue.push_back(odh.getTopLevelOutlines());
|
queue.push_back(odh.getTopLevelOutlines());
|
||||||
while (! queue.empty())
|
while (!queue.empty()) {
|
||||||
{
|
|
||||||
std::vector<QPDFOutlineObjectHelper>& outlines = *(queue.begin());
|
std::vector<QPDFOutlineObjectHelper>& outlines = *(queue.begin());
|
||||||
for (std::vector<QPDFOutlineObjectHelper>::iterator iter =
|
for (std::vector<QPDFOutlineObjectHelper>::iterator iter =
|
||||||
outlines.begin();
|
outlines.begin();
|
||||||
iter != outlines.end(); ++iter)
|
iter != outlines.end();
|
||||||
{
|
++iter) {
|
||||||
QPDFOutlineObjectHelper& ol = *iter;
|
QPDFOutlineObjectHelper& ol = *iter;
|
||||||
ol.getDestPage();
|
ol.getDestPage();
|
||||||
queue.push_back(ol.getKids());
|
queue.push_back(ol.getKids());
|
||||||
@ -208,21 +205,17 @@ FuzzHelper::run()
|
|||||||
// std::runtime_error. Throwing any other kind of exception,
|
// std::runtime_error. Throwing any other kind of exception,
|
||||||
// segfaulting, or having a memory error (when built with
|
// segfaulting, or having a memory error (when built with
|
||||||
// appropriate sanitizers) will all cause abnormal exit.
|
// appropriate sanitizers) will all cause abnormal exit.
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (QPDFExc const& e) {
|
||||||
catch (QPDFExc const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "QPDFExc: " << e.what() << std::endl;
|
std::cerr << "QPDFExc: " << e.what() << std::endl;
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
// Used by jpeg library to work around false positives in memory
|
// Used by jpeg library to work around false positives in memory
|
||||||
|
@ -34,17 +34,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size);
|
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size);
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int
|
||||||
|
main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++) {
|
||||||
{
|
|
||||||
PointerHolder<char> file_buf;
|
PointerHolder<char> file_buf;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
QUtil::read_file_into_memory(argv[i], file_buf, size);
|
QUtil::read_file_into_memory(argv[i], file_buf, size);
|
||||||
|
@ -26,8 +26,8 @@ void
|
|||||||
FuzzHelper::doChecks()
|
FuzzHelper::doChecks()
|
||||||
{
|
{
|
||||||
Pl_Discard discard;
|
Pl_Discard discard;
|
||||||
Pl_TIFFPredictor p("decoder", &discard,
|
Pl_TIFFPredictor p(
|
||||||
Pl_TIFFPredictor::a_decode, 16, 1, 8);
|
"decoder", &discard, Pl_TIFFPredictor::a_decode, 16, 1, 8);
|
||||||
p.write(const_cast<unsigned char*>(data), size);
|
p.write(const_cast<unsigned char*>(data), size);
|
||||||
p.finish();
|
p.finish();
|
||||||
}
|
}
|
||||||
@ -35,17 +35,15 @@ FuzzHelper::doChecks()
|
|||||||
void
|
void
|
||||||
FuzzHelper::run()
|
FuzzHelper::run()
|
||||||
{
|
{
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
doChecks();
|
doChecks();
|
||||||
}
|
} catch (std::runtime_error const& e) {
|
||||||
catch (std::runtime_error const& e)
|
|
||||||
{
|
|
||||||
std::cerr << "runtime_error: " << e.what() << std::endl;
|
std::cerr << "runtime_error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
extern "C" int
|
||||||
|
LLVMFuzzerTestOneInput(unsigned char const* data, size_t size)
|
||||||
{
|
{
|
||||||
FuzzHelper f(data, size);
|
FuzzHelper f(data, size);
|
||||||
f.run();
|
f.run();
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
class Buffer
|
class Buffer
|
||||||
{
|
{
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#ifndef QPDF_BUFFERINPUTSOURCE_HH
|
#ifndef QPDF_BUFFERINPUTSOURCE_HH
|
||||||
#define QPDF_BUFFERINPUTSOURCE_HH
|
#define QPDF_BUFFERINPUTSOURCE_HH
|
||||||
|
|
||||||
#include <qpdf/InputSource.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
#include <qpdf/Buffer.hh>
|
||||||
|
#include <qpdf/InputSource.hh>
|
||||||
|
|
||||||
class BufferInputSource: public InputSource
|
class BufferInputSource: public InputSource
|
||||||
{
|
{
|
||||||
@ -31,11 +31,11 @@ class BufferInputSource: public InputSource
|
|||||||
// If own_memory is true, BufferInputSource will delete the buffer
|
// If own_memory is true, BufferInputSource will delete the buffer
|
||||||
// when finished with it. Otherwise, the caller owns the memory.
|
// when finished with it. Otherwise, the caller owns the memory.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
BufferInputSource(std::string const& description, Buffer* buf,
|
BufferInputSource(
|
||||||
bool own_memory = false);
|
std::string const& description, Buffer* buf, bool own_memory = false);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
BufferInputSource(std::string const& description,
|
BufferInputSource(
|
||||||
std::string const& contents);
|
std::string const& description, std::string const& contents);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~BufferInputSource();
|
virtual ~BufferInputSource();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
@ -29,16 +29,15 @@
|
|||||||
|
|
||||||
/* Error Codes */
|
/* Error Codes */
|
||||||
|
|
||||||
enum qpdf_error_code_e
|
enum qpdf_error_code_e {
|
||||||
{
|
|
||||||
qpdf_e_success = 0,
|
qpdf_e_success = 0,
|
||||||
qpdf_e_internal, /* logic/programming error -- indicates bug */
|
qpdf_e_internal, /* logic/programming error -- indicates bug */
|
||||||
qpdf_e_system, /* I/O error, memory error, etc. */
|
qpdf_e_system, /* I/O error, memory error, etc. */
|
||||||
qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */
|
qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */
|
||||||
qpdf_e_password, /* incorrect password for encrypted file */
|
qpdf_e_password, /* incorrect password for encrypted file */
|
||||||
qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */
|
qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */
|
||||||
qpdf_e_pages, /* erroneous or unsupported pages structure */
|
qpdf_e_pages, /* erroneous or unsupported pages structure */
|
||||||
qpdf_e_object, /* type/bounds errors accessing objects */
|
qpdf_e_object, /* type/bounds errors accessing objects */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Object Types */
|
/* Object Types */
|
||||||
@ -75,62 +74,56 @@ enum qpdf_object_type_e {
|
|||||||
|
|
||||||
/* Write Parameters. See QPDFWriter.hh for details. */
|
/* Write Parameters. See QPDFWriter.hh for details. */
|
||||||
|
|
||||||
enum qpdf_object_stream_e
|
enum qpdf_object_stream_e {
|
||||||
{
|
qpdf_o_disable = 0, /* disable object streams */
|
||||||
qpdf_o_disable = 0, /* disable object streams */
|
qpdf_o_preserve, /* preserve object streams */
|
||||||
qpdf_o_preserve, /* preserve object streams */
|
qpdf_o_generate /* generate object streams */
|
||||||
qpdf_o_generate /* generate object streams */
|
|
||||||
};
|
};
|
||||||
enum qpdf_stream_data_e
|
enum qpdf_stream_data_e {
|
||||||
{
|
qpdf_s_uncompress = 0, /* uncompress stream data */
|
||||||
qpdf_s_uncompress = 0, /* uncompress stream data */
|
qpdf_s_preserve, /* preserve stream data compression */
|
||||||
qpdf_s_preserve, /* preserve stream data compression */
|
qpdf_s_compress /* compress stream data */
|
||||||
qpdf_s_compress /* compress stream data */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stream data flags */
|
/* Stream data flags */
|
||||||
|
|
||||||
/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */
|
/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */
|
||||||
enum qpdf_stream_encode_flags_e
|
enum qpdf_stream_encode_flags_e {
|
||||||
{
|
qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */
|
||||||
qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */
|
|
||||||
qpdf_ef_normalize = 1 << 1, /* normalize content stream */
|
qpdf_ef_normalize = 1 << 1, /* normalize content stream */
|
||||||
};
|
};
|
||||||
enum qpdf_stream_decode_level_e
|
enum qpdf_stream_decode_level_e {
|
||||||
{
|
|
||||||
/* These must be in order from less to more decoding. */
|
/* These must be in order from less to more decoding. */
|
||||||
qpdf_dl_none = 0, /* preserve all stream filters */
|
qpdf_dl_none = 0, /* preserve all stream filters */
|
||||||
qpdf_dl_generalized, /* decode general-purpose filters */
|
qpdf_dl_generalized, /* decode general-purpose filters */
|
||||||
qpdf_dl_specialized, /* also decode other non-lossy filters */
|
qpdf_dl_specialized, /* also decode other non-lossy filters */
|
||||||
qpdf_dl_all /* also decode lossy filters */
|
qpdf_dl_all /* also decode lossy filters */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* R3 Encryption Parameters */
|
/* R3 Encryption Parameters */
|
||||||
|
|
||||||
enum qpdf_r3_print_e
|
enum qpdf_r3_print_e {
|
||||||
{
|
qpdf_r3p_full = 0, /* allow all printing */
|
||||||
qpdf_r3p_full = 0, /* allow all printing */
|
qpdf_r3p_low, /* allow only low-resolution printing */
|
||||||
qpdf_r3p_low, /* allow only low-resolution printing */
|
qpdf_r3p_none /* allow no printing */
|
||||||
qpdf_r3p_none /* allow no printing */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It
|
/* 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
|
* corresponds to options in Acrobat 5's menus. The new interface in
|
||||||
* QPDFWriter offers more granularity and no longer uses this type.
|
* 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_annotate, /* Comments, fill forms, signing, assembly */
|
||||||
qpdf_r3m_form, /* Fill forms, signing, assembly */
|
qpdf_r3m_form, /* Fill forms, signing, assembly */
|
||||||
qpdf_r3m_assembly, /* Only document assembly */
|
qpdf_r3m_assembly, /* Only document assembly */
|
||||||
qpdf_r3m_none /* No modifications */
|
qpdf_r3m_none /* No modifications */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Form field flags from the PDF spec */
|
/* Form field flags from the PDF spec */
|
||||||
|
|
||||||
enum pdf_form_field_flag_e
|
enum pdf_form_field_flag_e {
|
||||||
{
|
|
||||||
/* flags that apply to all form fields */
|
/* flags that apply to all form fields */
|
||||||
ff_all_read_only = 1 << 0,
|
ff_all_read_only = 1 << 0,
|
||||||
ff_all_required = 1 << 1,
|
ff_all_required = 1 << 1,
|
||||||
@ -162,8 +155,7 @@ enum pdf_form_field_flag_e
|
|||||||
|
|
||||||
/* Annotation flags from the PDF spec */
|
/* Annotation flags from the PDF spec */
|
||||||
|
|
||||||
enum pdf_annotation_flag_e
|
enum pdf_annotation_flag_e {
|
||||||
{
|
|
||||||
an_invisible = 1 << 0,
|
an_invisible = 1 << 0,
|
||||||
an_hidden = 1 << 1,
|
an_hidden = 1 << 1,
|
||||||
an_print = 1 << 2,
|
an_print = 1 << 2,
|
||||||
@ -177,8 +169,7 @@ enum pdf_annotation_flag_e
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Encryption/password status for QPDFJob */
|
/* Encryption/password status for QPDFJob */
|
||||||
enum qpdf_encryption_status_e
|
enum qpdf_encryption_status_e {
|
||||||
{
|
|
||||||
qpdf_es_encrypted = 1 << 0,
|
qpdf_es_encrypted = 1 << 0,
|
||||||
qpdf_es_password_incorrect = 1 << 1
|
qpdf_es_password_incorrect = 1 << 1
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#if (defined _WIN32 || defined __CYGWIN__) && defined(DLL_EXPORT)
|
#if (defined _WIN32 || defined __CYGWIN__) && defined(DLL_EXPORT)
|
||||||
# define QPDF_DLL __declspec(dllexport)
|
# define QPDF_DLL __declspec(dllexport)
|
||||||
#elif defined __GNUC__
|
#elif defined __GNUC__
|
||||||
# define QPDF_DLL __attribute__ ((visibility ("default")))
|
# define QPDF_DLL __attribute__((visibility("default")))
|
||||||
#else
|
#else
|
||||||
# define QPDF_DLL
|
# define QPDF_DLL
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,12 +23,12 @@
|
|||||||
#define QPDF_INPUTSOURCE_HH
|
#define QPDF_INPUTSOURCE_HH
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
#include <qpdf/Types.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class QPDF_DLL_CLASS InputSource
|
class QPDF_DLL_CLASS InputSource
|
||||||
{
|
{
|
||||||
@ -71,13 +71,17 @@ class QPDF_DLL_CLASS InputSource
|
|||||||
// methods return true and leave the input source positioned
|
// methods return true and leave the input source positioned
|
||||||
// wherever check() left it at the end of the matching pattern.
|
// wherever check() left it at the end of the matching pattern.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool findFirst(char const* start_chars,
|
bool findFirst(
|
||||||
qpdf_offset_t offset, size_t len,
|
char const* start_chars,
|
||||||
Finder& finder);
|
qpdf_offset_t offset,
|
||||||
|
size_t len,
|
||||||
|
Finder& finder);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool findLast(char const* start_chars,
|
bool findLast(
|
||||||
qpdf_offset_t offset, size_t len,
|
char const* start_chars,
|
||||||
Finder& finder);
|
qpdf_offset_t offset,
|
||||||
|
size_t len,
|
||||||
|
Finder& finder);
|
||||||
|
|
||||||
virtual qpdf_offset_t findAndSkipNextEOL() = 0;
|
virtual qpdf_offset_t findAndSkipNextEOL() = 0;
|
||||||
virtual std::string const& getName() const = 0;
|
virtual std::string const& getName() const = 0;
|
||||||
|
@ -38,12 +38,12 @@
|
|||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class JSON
|
class JSON
|
||||||
{
|
{
|
||||||
@ -134,14 +134,13 @@ class JSON
|
|||||||
f_optional = 1 << 0,
|
f_optional = 1 << 0,
|
||||||
};
|
};
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool checkSchema(JSON schema, unsigned long flags,
|
bool checkSchema(
|
||||||
std::list<std::string>& errors);
|
JSON schema, unsigned long flags, std::list<std::string>& errors);
|
||||||
|
|
||||||
// Same as passing 0 for flags
|
// Same as passing 0 for flags
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool checkSchema(JSON schema, std::list<std::string>& errors);
|
bool checkSchema(JSON schema, std::list<std::string>& errors);
|
||||||
|
|
||||||
|
|
||||||
// Create a JSON object from a string.
|
// Create a JSON object from a string.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static JSON parse(std::string const&);
|
static JSON parse(std::string const&);
|
||||||
@ -198,11 +197,12 @@ class JSON
|
|||||||
|
|
||||||
JSON(std::shared_ptr<JSON_value>);
|
JSON(std::shared_ptr<JSON_value>);
|
||||||
|
|
||||||
static bool
|
static bool checkSchemaInternal(
|
||||||
checkSchemaInternal(JSON_value* this_v, JSON_value* sch_v,
|
JSON_value* this_v,
|
||||||
unsigned long flags,
|
JSON_value* sch_v,
|
||||||
std::list<std::string>& errors,
|
unsigned long flags,
|
||||||
std::string prefix);
|
std::list<std::string>& errors,
|
||||||
|
std::string prefix);
|
||||||
|
|
||||||
class Members
|
class Members
|
||||||
{
|
{
|
||||||
@ -222,5 +222,4 @@ class JSON
|
|||||||
PointerHolder<Members> m;
|
PointerHolder<Members> m;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // JSON_HH
|
#endif // JSON_HH
|
||||||
|
@ -47,8 +47,8 @@
|
|||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class QPDF_DLL_CLASS Pipeline
|
class QPDF_DLL_CLASS Pipeline
|
||||||
{
|
{
|
||||||
|
@ -33,9 +33,9 @@
|
|||||||
// For this pipeline, "next" may be null. If a next pointer is
|
// For this pipeline, "next" may be null. If a next pointer is
|
||||||
// provided, this pipeline will also pass the data through to it.
|
// provided, this pipeline will also pass the data through to it.
|
||||||
|
|
||||||
|
#include <qpdf/Buffer.hh>
|
||||||
#include <qpdf/Pipeline.hh>
|
#include <qpdf/Pipeline.hh>
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
#include <qpdf/Buffer.hh>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ class Pl_Buffer: public Pipeline
|
|||||||
// a buffer of size *len allocated with malloc(). It is the
|
// a buffer of size *len allocated with malloc(). It is the
|
||||||
// caller's responsibility to call free() on the buffer.
|
// caller's responsibility to call free() on the buffer.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void getMallocBuffer(unsigned char **buf, size_t* len);
|
void getMallocBuffer(unsigned char** buf, size_t* len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Members
|
class Members
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
// This pipeline is reusable; i.e., it is safe to call write() after
|
// This pipeline is reusable; i.e., it is safe to call write() after
|
||||||
// calling finish().
|
// calling finish().
|
||||||
|
|
||||||
#include <qpdf/Types.h>
|
|
||||||
#include <qpdf/Pipeline.hh>
|
#include <qpdf/Pipeline.hh>
|
||||||
|
#include <qpdf/Types.h>
|
||||||
|
|
||||||
class Pl_Count: public Pipeline
|
class Pl_Count: public Pipeline
|
||||||
{
|
{
|
||||||
|
@ -52,12 +52,14 @@ class Pl_DCT: public Pipeline
|
|||||||
|
|
||||||
// Constructor for compressing image data
|
// Constructor for compressing image data
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Pl_DCT(char const* identifier, Pipeline* next,
|
Pl_DCT(
|
||||||
JDIMENSION image_width,
|
char const* identifier,
|
||||||
JDIMENSION image_height,
|
Pipeline* next,
|
||||||
int components,
|
JDIMENSION image_width,
|
||||||
J_COLOR_SPACE color_space,
|
JDIMENSION image_height,
|
||||||
CompressConfig* config_callback = 0);
|
int components,
|
||||||
|
J_COLOR_SPACE color_space,
|
||||||
|
CompressConfig* config_callback = 0);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~Pl_DCT();
|
virtual ~Pl_DCT();
|
||||||
@ -82,13 +84,14 @@ class Pl_DCT: public Pipeline
|
|||||||
~Members();
|
~Members();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Members(action_e action,
|
Members(
|
||||||
char const* buf_description,
|
action_e action,
|
||||||
JDIMENSION image_width = 0,
|
char const* buf_description,
|
||||||
JDIMENSION image_height = 0,
|
JDIMENSION image_width = 0,
|
||||||
int components = 1,
|
JDIMENSION image_height = 0,
|
||||||
J_COLOR_SPACE color_space = JCS_GRAYSCALE,
|
int components = 1,
|
||||||
CompressConfig* config_callback = 0);
|
J_COLOR_SPACE color_space = JCS_GRAYSCALE,
|
||||||
|
CompressConfig* config_callback = 0);
|
||||||
Members(Members const&);
|
Members(Members const&);
|
||||||
|
|
||||||
action_e action;
|
action_e action;
|
||||||
|
@ -35,8 +35,11 @@ class Pl_Flate: public Pipeline
|
|||||||
enum action_e { a_inflate, a_deflate };
|
enum action_e { a_inflate, a_deflate };
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Pl_Flate(char const* identifier, Pipeline* next,
|
Pl_Flate(
|
||||||
action_e action, unsigned int out_bufsize = def_bufsize);
|
char const* identifier,
|
||||||
|
Pipeline* next,
|
||||||
|
action_e action,
|
||||||
|
unsigned int out_bufsize = def_bufsize);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~Pl_Flate();
|
virtual ~Pl_Flate();
|
||||||
|
|
||||||
|
@ -24,10 +24,10 @@
|
|||||||
|
|
||||||
#include <qpdf/Pipeline.hh>
|
#include <qpdf/Pipeline.hh>
|
||||||
|
|
||||||
#include <qpdf/QPDFTokenizer.hh>
|
#include <qpdf/Pl_Buffer.hh>
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
#include <qpdf/Pl_Buffer.hh>
|
#include <qpdf/QPDFTokenizer.hh>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -48,9 +48,10 @@ class Pl_QPDFTokenizer: public Pipeline
|
|||||||
// pipeline that the token filter writes to. If next is not
|
// pipeline that the token filter writes to. If next is not
|
||||||
// provided, any output written by the filter will be discarded.
|
// provided, any output written by the filter will be discarded.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Pl_QPDFTokenizer(char const* identifier,
|
Pl_QPDFTokenizer(
|
||||||
QPDFObjectHandle::TokenFilter* filter,
|
char const* identifier,
|
||||||
Pipeline* next = 0);
|
QPDFObjectHandle::TokenFilter* filter,
|
||||||
|
Pipeline* next = 0);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~Pl_QPDFTokenizer();
|
virtual ~Pl_QPDFTokenizer();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
@ -30,8 +30,7 @@ class Pl_RunLength: public Pipeline
|
|||||||
enum action_e { a_encode, a_decode };
|
enum action_e { a_encode, a_decode };
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Pl_RunLength(char const* identifier, Pipeline* next,
|
Pl_RunLength(char const* identifier, Pipeline* next, action_e action);
|
||||||
action_e action);
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~Pl_RunLength();
|
virtual ~Pl_RunLength();
|
||||||
|
|
||||||
|
@ -187,18 +187,16 @@ class PointerHolder
|
|||||||
}
|
}
|
||||||
~Data()
|
~Data()
|
||||||
{
|
{
|
||||||
if (array)
|
if (array) {
|
||||||
{
|
delete[] this->pointer;
|
||||||
delete [] this->pointer;
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete this->pointer;
|
delete this->pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
T* pointer;
|
T* pointer;
|
||||||
bool array;
|
bool array;
|
||||||
int refcount;
|
int refcount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Data(Data const&) = delete;
|
Data(Data const&) = delete;
|
||||||
Data& operator=(Data const&) = delete;
|
Data& operator=(Data const&) = delete;
|
||||||
@ -208,7 +206,7 @@ class PointerHolder
|
|||||||
#if POINTERHOLDER_TRANSITION >= 1
|
#if POINTERHOLDER_TRANSITION >= 1
|
||||||
explicit
|
explicit
|
||||||
#endif // POINTERHOLDER_TRANSITION >= 1
|
#endif // POINTERHOLDER_TRANSITION >= 1
|
||||||
PointerHolder(T* pointer = 0)
|
PointerHolder(T* pointer = 0)
|
||||||
{
|
{
|
||||||
this->init(new Data(pointer, false));
|
this->init(new Data(pointer, false));
|
||||||
}
|
}
|
||||||
@ -222,16 +220,17 @@ class PointerHolder
|
|||||||
{
|
{
|
||||||
this->copy(rhs);
|
this->copy(rhs);
|
||||||
}
|
}
|
||||||
PointerHolder& operator=(PointerHolder const& rhs)
|
PointerHolder&
|
||||||
|
operator=(PointerHolder const& rhs)
|
||||||
{
|
{
|
||||||
if (this != &rhs)
|
if (this != &rhs) {
|
||||||
{
|
|
||||||
this->destroy();
|
this->destroy();
|
||||||
this->copy(rhs);
|
this->copy(rhs);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
PointerHolder& operator=(decltype(nullptr))
|
PointerHolder&
|
||||||
|
operator=(decltype(nullptr))
|
||||||
{
|
{
|
||||||
this->operator=(PointerHolder<T>());
|
this->operator=(PointerHolder<T>());
|
||||||
return *this;
|
return *this;
|
||||||
@ -240,21 +239,25 @@ class PointerHolder
|
|||||||
{
|
{
|
||||||
this->destroy();
|
this->destroy();
|
||||||
}
|
}
|
||||||
bool operator==(PointerHolder const& rhs) const
|
bool
|
||||||
|
operator==(PointerHolder const& rhs) const
|
||||||
{
|
{
|
||||||
return this->data->pointer == rhs.data->pointer;
|
return this->data->pointer == rhs.data->pointer;
|
||||||
}
|
}
|
||||||
bool operator==(decltype(nullptr)) const
|
bool
|
||||||
|
operator==(decltype(nullptr)) const
|
||||||
{
|
{
|
||||||
return this->data->pointer == nullptr;
|
return this->data->pointer == nullptr;
|
||||||
}
|
}
|
||||||
bool operator<(PointerHolder const& rhs) const
|
bool
|
||||||
|
operator<(PointerHolder const& rhs) const
|
||||||
{
|
{
|
||||||
return this->data->pointer < rhs.data->pointer;
|
return this->data->pointer < rhs.data->pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get() is for interface compatibility with std::shared_ptr
|
// get() is for interface compatibility with std::shared_ptr
|
||||||
T* get() const
|
T*
|
||||||
|
get() const
|
||||||
{
|
{
|
||||||
return this->data->pointer;
|
return this->data->pointer;
|
||||||
}
|
}
|
||||||
@ -264,70 +267,79 @@ class PointerHolder
|
|||||||
#if POINTERHOLDER_TRANSITION >= 2
|
#if POINTERHOLDER_TRANSITION >= 2
|
||||||
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
||||||
#endif // POINTERHOLDER_TRANSITION >= 2
|
#endif // POINTERHOLDER_TRANSITION >= 2
|
||||||
T* getPointer()
|
T*
|
||||||
|
getPointer()
|
||||||
{
|
{
|
||||||
return this->data->pointer;
|
return this->data->pointer;
|
||||||
}
|
}
|
||||||
#if POINTERHOLDER_TRANSITION >= 2
|
#if POINTERHOLDER_TRANSITION >= 2
|
||||||
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
||||||
#endif // POINTERHOLDER_TRANSITION >= 2
|
#endif // POINTERHOLDER_TRANSITION >= 2
|
||||||
T const* getPointer() const
|
T const*
|
||||||
|
getPointer() const
|
||||||
{
|
{
|
||||||
return this->data->pointer;
|
return this->data->pointer;
|
||||||
}
|
}
|
||||||
#if POINTERHOLDER_TRANSITION >= 2
|
#if POINTERHOLDER_TRANSITION >= 2
|
||||||
[[deprecated("use use_count() instead of getRefcount()")]]
|
[[deprecated("use use_count() instead of getRefcount()")]]
|
||||||
#endif // POINTERHOLDER_TRANSITION >= 2
|
#endif // POINTERHOLDER_TRANSITION >= 2
|
||||||
int getRefcount() const
|
int
|
||||||
|
getRefcount() const
|
||||||
{
|
{
|
||||||
return this->data->refcount;
|
return this->data->refcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// use_count() is for compatibility with std::shared_ptr
|
// use_count() is for compatibility with std::shared_ptr
|
||||||
long use_count()
|
long
|
||||||
|
use_count()
|
||||||
{
|
{
|
||||||
return static_cast<long>(this->data->refcount);
|
return static_cast<long>(this->data->refcount);
|
||||||
}
|
}
|
||||||
|
|
||||||
T const& operator*() const
|
T const&
|
||||||
|
operator*() const
|
||||||
{
|
{
|
||||||
return *this->data->pointer;
|
return *this->data->pointer;
|
||||||
}
|
}
|
||||||
T& operator*()
|
T&
|
||||||
|
operator*()
|
||||||
{
|
{
|
||||||
return *this->data->pointer;
|
return *this->data->pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
T const* operator->() const
|
T const*
|
||||||
|
operator->() const
|
||||||
{
|
{
|
||||||
return this->data->pointer;
|
return this->data->pointer;
|
||||||
}
|
}
|
||||||
T* operator->()
|
T*
|
||||||
|
operator->()
|
||||||
{
|
{
|
||||||
return this->data->pointer;
|
return this->data->pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(Data* data)
|
void
|
||||||
|
init(Data* data)
|
||||||
{
|
{
|
||||||
this->data = data;
|
this->data = data;
|
||||||
++this->data->refcount;
|
++this->data->refcount;
|
||||||
}
|
}
|
||||||
void copy(PointerHolder const& rhs)
|
void
|
||||||
|
copy(PointerHolder const& rhs)
|
||||||
{
|
{
|
||||||
this->init(rhs.data);
|
this->init(rhs.data);
|
||||||
}
|
}
|
||||||
void destroy()
|
void
|
||||||
|
destroy()
|
||||||
{
|
{
|
||||||
bool gone = false;
|
bool gone = false;
|
||||||
{
|
{
|
||||||
if (--this->data->refcount == 0)
|
if (--this->data->refcount == 0) {
|
||||||
{
|
|
||||||
gone = true;
|
gone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gone)
|
if (gone) {
|
||||||
{
|
|
||||||
delete this->data;
|
delete this->data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,7 +347,7 @@ class PointerHolder
|
|||||||
Data* data;
|
Data* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename... _Args>
|
template <typename T, typename... _Args>
|
||||||
inline PointerHolder<T>
|
inline PointerHolder<T>
|
||||||
make_pointer_holder(_Args&&... __args)
|
make_pointer_holder(_Args&&... __args)
|
||||||
{
|
{
|
||||||
|
@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
#include <stdexcept>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
|
||||||
#include <cassert>
|
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
// This namespace provides safe integer conversion that detects
|
// This namespace provides safe integer conversion that detects
|
||||||
@ -51,9 +51,11 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
// throws a range_error otherwise. This class is specialized for
|
// throws a range_error otherwise. This class is specialized for
|
||||||
// each permutation of signed/unsigned for the From and To
|
// each permutation of signed/unsigned for the From and To
|
||||||
// classes.
|
// classes.
|
||||||
template <typename From, typename To,
|
template <
|
||||||
bool From_signed = std::numeric_limits<From>::is_signed,
|
typename From,
|
||||||
bool To_signed = std::numeric_limits<To>::is_signed>
|
typename To,
|
||||||
|
bool From_signed = std::numeric_limits<From>::is_signed,
|
||||||
|
bool To_signed = std::numeric_limits<To>::is_signed>
|
||||||
class IntConverter
|
class IntConverter
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@ -62,17 +64,16 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
class IntConverter<From, To, false, false>
|
class IntConverter<From, To, false, false>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static To convert(From const& i)
|
static To
|
||||||
|
convert(From const& i)
|
||||||
{
|
{
|
||||||
// From and To are both unsigned.
|
// From and To are both unsigned.
|
||||||
if (i > std::numeric_limits<To>::max())
|
if (i > std::numeric_limits<To>::max()) {
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "integer out of range converting " << i
|
msg << "integer out of range converting " << i << " from a "
|
||||||
<< " from a "
|
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
|
||||||
<< sizeof(From) << "-byte unsigned type to a "
|
<< "-byte unsigned type";
|
||||||
<< sizeof(To) << "-byte unsigned type";
|
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
}
|
||||||
return static_cast<To>(i);
|
return static_cast<To>(i);
|
||||||
@ -83,18 +84,17 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
class IntConverter<From, To, true, true>
|
class IntConverter<From, To, true, true>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static To convert(From const& i)
|
static To
|
||||||
|
convert(From const& i)
|
||||||
{
|
{
|
||||||
// From and To are both signed.
|
// From and To are both signed.
|
||||||
if ((i < std::numeric_limits<To>::min()) ||
|
if ((i < std::numeric_limits<To>::min()) ||
|
||||||
(i > std::numeric_limits<To>::max()))
|
(i > std::numeric_limits<To>::max())) {
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "integer out of range converting " << i
|
msg << "integer out of range converting " << i << " from a "
|
||||||
<< " from a "
|
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
|
||||||
<< sizeof(From) << "-byte signed type to a "
|
<< "-byte signed type";
|
||||||
<< sizeof(To) << "-byte signed type";
|
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
}
|
||||||
return static_cast<To>(i);
|
return static_cast<To>(i);
|
||||||
@ -105,20 +105,19 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
class IntConverter<From, To, true, false>
|
class IntConverter<From, To, true, false>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static To convert(From const& i)
|
static To
|
||||||
|
convert(From const& i)
|
||||||
{
|
{
|
||||||
// From is signed, and To is unsigned. If i > 0, it's safe to
|
// From is signed, and To is unsigned. If i > 0, it's safe to
|
||||||
// convert it to the corresponding unsigned type and to
|
// convert it to the corresponding unsigned type and to
|
||||||
// compare with To's max.
|
// compare with To's max.
|
||||||
auto ii = static_cast<typename to_u<From>::type>(i);
|
auto ii = static_cast<typename to_u<From>::type>(i);
|
||||||
if ((i < 0) || (ii > std::numeric_limits<To>::max()))
|
if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "integer out of range converting " << i
|
msg << "integer out of range converting " << i << " from a "
|
||||||
<< " from a "
|
<< sizeof(From) << "-byte signed type to a " << sizeof(To)
|
||||||
<< sizeof(From) << "-byte signed type to a "
|
<< "-byte unsigned type";
|
||||||
<< sizeof(To) << "-byte unsigned type";
|
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
}
|
||||||
return static_cast<To>(i);
|
return static_cast<To>(i);
|
||||||
@ -129,20 +128,19 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
class IntConverter<From, To, false, true>
|
class IntConverter<From, To, false, true>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static To convert(From const& i)
|
static To
|
||||||
|
convert(From const& i)
|
||||||
{
|
{
|
||||||
// From is unsigned, and to is signed. Convert To's max to the
|
// From is unsigned, and to is signed. Convert To's max to the
|
||||||
// unsigned version of To and compare i against that.
|
// unsigned version of To and compare i against that.
|
||||||
auto maxval = static_cast<typename to_u<To>::type>(
|
auto maxval = static_cast<typename to_u<To>::type>(
|
||||||
std::numeric_limits<To>::max());
|
std::numeric_limits<To>::max());
|
||||||
if (i > maxval)
|
if (i > maxval) {
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "integer out of range converting " << i
|
msg << "integer out of range converting " << i << " from a "
|
||||||
<< " from a "
|
<< sizeof(From) << "-byte unsigned type to a " << sizeof(To)
|
||||||
<< sizeof(From) << "-byte unsigned type to a "
|
<< "-byte signed type";
|
||||||
<< sizeof(To) << "-byte signed type";
|
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
}
|
||||||
return static_cast<To>(i);
|
return static_cast<To>(i);
|
||||||
@ -152,97 +150,105 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
// Specific converters. The return type of each function must match
|
// Specific converters. The return type of each function must match
|
||||||
// the second template parameter to IntConverter.
|
// the second template parameter to IntConverter.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
char to_char(T const& i)
|
char
|
||||||
|
to_char(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, char>::convert(i);
|
return IntConverter<T, char>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
unsigned char to_uchar(T const& i)
|
unsigned char
|
||||||
|
to_uchar(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, unsigned char>::convert(i);
|
return IntConverter<T, unsigned char>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
short to_short(T const& i)
|
short
|
||||||
|
to_short(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, short>::convert(i);
|
return IntConverter<T, short>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
unsigned short to_ushort(T const& i)
|
unsigned short
|
||||||
|
to_ushort(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, unsigned short>::convert(i);
|
return IntConverter<T, unsigned short>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int to_int(T const& i)
|
int
|
||||||
|
to_int(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, int>::convert(i);
|
return IntConverter<T, int>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
unsigned int to_uint(T const& i)
|
unsigned int
|
||||||
|
to_uint(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, unsigned int>::convert(i);
|
return IntConverter<T, unsigned int>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
size_t to_size(T const& i)
|
size_t
|
||||||
|
to_size(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, size_t>::convert(i);
|
return IntConverter<T, size_t>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
qpdf_offset_t to_offset(T const& i)
|
qpdf_offset_t
|
||||||
|
to_offset(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, qpdf_offset_t>::convert(i);
|
return IntConverter<T, qpdf_offset_t>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
long to_long(T const& i)
|
long
|
||||||
|
to_long(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, long >::convert(i);
|
return IntConverter<T, long>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
unsigned long to_ulong(T const& i)
|
unsigned long
|
||||||
|
to_ulong(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, unsigned long >::convert(i);
|
return IntConverter<T, unsigned long>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
long long to_longlong(T const& i)
|
long long
|
||||||
|
to_longlong(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, long long>::convert(i);
|
return IntConverter<T, long long>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
unsigned long long to_ulonglong(T const& i)
|
unsigned long long
|
||||||
|
to_ulonglong(T const& i)
|
||||||
{
|
{
|
||||||
return IntConverter<T, unsigned long long>::convert(i);
|
return IntConverter<T, unsigned long long>::convert(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void range_check(T const& cur, T const& delta)
|
void
|
||||||
|
range_check(T const& cur, T const& delta)
|
||||||
{
|
{
|
||||||
if ((delta > 0) != (cur > 0))
|
if ((delta > 0) != (cur > 0)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((delta > 0) &&
|
if ((delta > 0) && ((std::numeric_limits<T>::max() - cur) < delta)) {
|
||||||
((std::numeric_limits<T>::max() - cur) < delta))
|
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "adding " << delta << " to " << cur
|
msg << "adding " << delta << " to " << cur
|
||||||
<< " would cause an integer overflow";
|
<< " would cause an integer overflow";
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
} else if (
|
||||||
else if ((delta < 0) &&
|
(delta < 0) && ((std::numeric_limits<T>::min() - cur) > delta)) {
|
||||||
((std::numeric_limits<T>::min() - cur) > delta))
|
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "adding " << delta << " to " << cur
|
msg << "adding " << delta << " to " << cur
|
||||||
@ -252,25 +258,21 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void range_check_substract(T const& cur, T const& delta)
|
void
|
||||||
|
range_check_substract(T const& cur, T const& delta)
|
||||||
{
|
{
|
||||||
if ((delta >= 0) == (cur >= 0))
|
if ((delta >= 0) == (cur >= 0)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((delta > 0) &&
|
if ((delta > 0) && ((std::numeric_limits<T>::min() + delta) > cur)) {
|
||||||
((std::numeric_limits<T>::min() + delta) > cur))
|
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "subtracting " << delta << " from " << cur
|
msg << "subtracting " << delta << " from " << cur
|
||||||
<< " would cause an integer underflow";
|
<< " would cause an integer underflow";
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
} else if (
|
||||||
else if ((delta < 0) &&
|
(delta < 0) && ((std::numeric_limits<T>::max() + delta) < cur)) {
|
||||||
((std::numeric_limits<T>::max() + delta) < cur))
|
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "subtracting " << delta << " from " << cur
|
msg << "subtracting " << delta << " from " << cur
|
||||||
@ -278,6 +280,6 @@ namespace QIntC // QIntC = qpdf Integer Conversion
|
|||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}; // namespace QIntC
|
||||||
|
|
||||||
#endif // QINTC_HH
|
#endif // QINTC_HH
|
||||||
|
@ -25,26 +25,25 @@
|
|||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <qpdf/QIntC.hh>
|
|
||||||
#include <qpdf/QPDFExc.hh>
|
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/QPDFObjGen.hh>
|
|
||||||
#include <qpdf/QPDFXRefEntry.hh>
|
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/QPDFTokenizer.hh>
|
|
||||||
#include <qpdf/QPDFStreamFilter.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
#include <qpdf/Buffer.hh>
|
||||||
#include <qpdf/InputSource.hh>
|
#include <qpdf/InputSource.hh>
|
||||||
#include <qpdf/PDFVersion.hh>
|
#include <qpdf/PDFVersion.hh>
|
||||||
|
#include <qpdf/QIntC.hh>
|
||||||
|
#include <qpdf/QPDFExc.hh>
|
||||||
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
|
#include <qpdf/QPDFStreamFilter.hh>
|
||||||
|
#include <qpdf/QPDFTokenizer.hh>
|
||||||
|
#include <qpdf/QPDFXRefEntry.hh>
|
||||||
|
|
||||||
class QPDF_Stream;
|
class QPDF_Stream;
|
||||||
class BitStream;
|
class BitStream;
|
||||||
@ -87,24 +86,29 @@ class QPDF
|
|||||||
// file will be closed at the end. Otherwise, the caller is
|
// file will be closed at the end. Otherwise, the caller is
|
||||||
// responsible for closing the file.
|
// responsible for closing the file.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void processFile(char const* description, FILE* file,
|
void processFile(
|
||||||
bool close_file, char const* password = 0);
|
char const* description,
|
||||||
|
FILE* file,
|
||||||
|
bool close_file,
|
||||||
|
char const* password = 0);
|
||||||
|
|
||||||
// Parse a PDF file loaded into a memory buffer. This works
|
// Parse a PDF file loaded into a memory buffer. This works
|
||||||
// exactly like processFile except that the PDF file is in memory
|
// exactly like processFile except that the PDF file is in memory
|
||||||
// instead of on disk. The description appears in any warning or
|
// instead of on disk. The description appears in any warning or
|
||||||
// error message in place of the file name.
|
// error message in place of the file name.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void processMemoryFile(char const* description,
|
void processMemoryFile(
|
||||||
char const* buf, size_t length,
|
char const* description,
|
||||||
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
|
// Parse a PDF file loaded from a custom InputSource. If you have
|
||||||
// your own method of retrieving a PDF file, you can subclass
|
// your own method of retrieving a PDF file, you can subclass
|
||||||
// InputSource and use this method.
|
// InputSource and use this method.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void processInputSource(PointerHolder<InputSource>,
|
void
|
||||||
char const* password = 0);
|
processInputSource(PointerHolder<InputSource>, char const* password = 0);
|
||||||
|
|
||||||
// Close or otherwise release the input source. Once this has been
|
// Close or otherwise release the input source. Once this has been
|
||||||
// called, no other methods of qpdf can be called safely except
|
// called, no other methods of qpdf can be called safely except
|
||||||
@ -149,7 +153,7 @@ class QPDF
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static void registerStreamFilter(
|
static void registerStreamFilter(
|
||||||
std::string const& filter_name,
|
std::string const& filter_name,
|
||||||
std::function<std::shared_ptr<QPDFStreamFilter> ()> factory);
|
std::function<std::shared_ptr<QPDFStreamFilter>()> factory);
|
||||||
|
|
||||||
// Parameter settings
|
// Parameter settings
|
||||||
|
|
||||||
@ -312,8 +316,7 @@ class QPDF
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2);
|
void swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void swapObjects(int objid1, int generation1,
|
void swapObjects(int objid1, int generation1, int objid2, int generation2);
|
||||||
int objid2, int generation2);
|
|
||||||
|
|
||||||
// Replace a reserved object. This is a wrapper around
|
// Replace a reserved object. This is a wrapper around
|
||||||
// replaceObject but it guarantees that the underlying object is a
|
// replaceObject but it guarantees that the underlying object is a
|
||||||
@ -321,8 +324,7 @@ class QPDF
|
|||||||
// to replacement.
|
// to replacement.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void
|
void
|
||||||
replaceReserved(QPDFObjectHandle reserved,
|
replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement);
|
||||||
QPDFObjectHandle replacement);
|
|
||||||
|
|
||||||
// Copy an object from another QPDF to this one. Starting with
|
// Copy an object from another QPDF to this one. Starting with
|
||||||
// qpdf version 8.3.0, it is no longer necessary to keep the
|
// qpdf version 8.3.0, it is no longer necessary to keep the
|
||||||
@ -377,13 +379,19 @@ class QPDF
|
|||||||
class EncryptionData
|
class EncryptionData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// This class holds data read from the encryption dictionary.
|
// This class holds data read from the encryption dictionary.
|
||||||
EncryptionData(int V, int R, int Length_bytes, int P,
|
EncryptionData(
|
||||||
std::string const& O, std::string const& U,
|
int V,
|
||||||
std::string const& OE, std::string const& UE,
|
int R,
|
||||||
std::string const& Perms,
|
int Length_bytes,
|
||||||
std::string const& id1, bool encrypt_metadata) :
|
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),
|
V(V),
|
||||||
R(R),
|
R(R),
|
||||||
Length_bytes(Length_bytes),
|
Length_bytes(Length_bytes),
|
||||||
@ -412,11 +420,12 @@ class QPDF
|
|||||||
|
|
||||||
void setO(std::string const&);
|
void setO(std::string const&);
|
||||||
void setU(std::string const&);
|
void setU(std::string const&);
|
||||||
void setV5EncryptionParameters(std::string const& O,
|
void setV5EncryptionParameters(
|
||||||
std::string const& OE,
|
std::string const& O,
|
||||||
std::string const& U,
|
std::string const& OE,
|
||||||
std::string const& UE,
|
std::string const& U,
|
||||||
std::string const& Perms);
|
std::string const& UE,
|
||||||
|
std::string const& Perms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncryptionData(EncryptionData const&) = delete;
|
EncryptionData(EncryptionData const&) = delete;
|
||||||
@ -442,10 +451,13 @@ class QPDF
|
|||||||
bool isEncrypted(int& R, int& P);
|
bool isEncrypted(int& R, int& P);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool isEncrypted(int& R, int& P, int& V,
|
bool isEncrypted(
|
||||||
encryption_method_e& stream_method,
|
int& R,
|
||||||
encryption_method_e& string_method,
|
int& P,
|
||||||
encryption_method_e& file_method);
|
int& V,
|
||||||
|
encryption_method_e& stream_method,
|
||||||
|
encryption_method_e& string_method,
|
||||||
|
encryption_method_e& file_method);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool ownerPasswordMatched() const;
|
bool ownerPasswordMatched() const;
|
||||||
@ -480,26 +492,44 @@ class QPDF
|
|||||||
static void trim_user_password(std::string& user_password);
|
static void trim_user_password(std::string& user_password);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static std::string compute_data_key(
|
static std::string compute_data_key(
|
||||||
std::string const& encryption_key, int objid, int generation,
|
std::string const& encryption_key,
|
||||||
bool use_aes, int encryption_V, int encryption_R);
|
int objid,
|
||||||
|
int generation,
|
||||||
|
bool use_aes,
|
||||||
|
int encryption_V,
|
||||||
|
int encryption_R);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static std::string compute_encryption_key(
|
static std::string compute_encryption_key(
|
||||||
std::string const& password, EncryptionData const& data);
|
std::string const& password, EncryptionData const& data);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static void compute_encryption_O_U(
|
static void compute_encryption_O_U(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
int V, int R, int key_len, int P, bool encrypt_metadata,
|
char const* owner_password,
|
||||||
|
int V,
|
||||||
|
int R,
|
||||||
|
int key_len,
|
||||||
|
int P,
|
||||||
|
bool encrypt_metadata,
|
||||||
std::string const& id1,
|
std::string const& id1,
|
||||||
std::string& O, std::string& U);
|
std::string& O,
|
||||||
|
std::string& U);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static void compute_encryption_parameters_V5(
|
static void compute_encryption_parameters_V5(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
int V, int R, int key_len, int P, bool encrypt_metadata,
|
char const* owner_password,
|
||||||
|
int V,
|
||||||
|
int R,
|
||||||
|
int key_len,
|
||||||
|
int P,
|
||||||
|
bool encrypt_metadata,
|
||||||
std::string const& id1,
|
std::string const& id1,
|
||||||
std::string& encryption_key,
|
std::string& encryption_key,
|
||||||
std::string& O, std::string& U,
|
std::string& O,
|
||||||
std::string& OE, std::string& UE, std::string& Perms);
|
std::string& U,
|
||||||
|
std::string& OE,
|
||||||
|
std::string& UE,
|
||||||
|
std::string& Perms);
|
||||||
// Return the full user password as stored in the PDF file. For
|
// Return the full user password as stored in the PDF file. For
|
||||||
// files encrypted with 40-bit or 128-bit keys, the user password
|
// files encrypted with 40-bit or 128-bit keys, the user password
|
||||||
// can be recovered when the file is opened using the owner
|
// can be recovered when the file is opened using the owner
|
||||||
@ -587,8 +617,9 @@ class QPDF
|
|||||||
// keys. This is used by QPDFWriter to avoid creation of dangling
|
// keys. This is used by QPDFWriter to avoid creation of dangling
|
||||||
// objects for stream dictionary keys it will be regenerating.
|
// objects for stream dictionary keys it will be regenerating.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void optimize(std::map<int, int> const& object_stream_data,
|
void optimize(
|
||||||
bool allow_changes = true);
|
std::map<int, int> const& object_stream_data,
|
||||||
|
bool allow_changes = true);
|
||||||
// ABI: make function optional and merge overloaded versions
|
// ABI: make function optional and merge overloaded versions
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void optimize(
|
void optimize(
|
||||||
@ -650,8 +681,8 @@ class QPDF
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void addPage(QPDFObjectHandle newpage, bool first);
|
void addPage(QPDFObjectHandle newpage, bool first);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void addPageAt(QPDFObjectHandle newpage, bool before,
|
void
|
||||||
QPDFObjectHandle refpage);
|
addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void removePage(QPDFObjectHandle page);
|
void removePage(QPDFObjectHandle page);
|
||||||
// End legacy page helpers
|
// End legacy page helpers
|
||||||
@ -661,9 +692,10 @@ class QPDF
|
|||||||
class Writer
|
class Writer
|
||||||
{
|
{
|
||||||
friend class QPDFWriter;
|
friend class QPDFWriter;
|
||||||
private:
|
|
||||||
|
|
||||||
static void getLinearizedParts(
|
private:
|
||||||
|
static void
|
||||||
|
getLinearizedParts(
|
||||||
QPDF& qpdf,
|
QPDF& qpdf,
|
||||||
std::map<int, int> const& object_stream_data,
|
std::map<int, int> const& object_stream_data,
|
||||||
std::vector<QPDFObjectHandle>& part4,
|
std::vector<QPDFObjectHandle>& part4,
|
||||||
@ -672,28 +704,32 @@ class QPDF
|
|||||||
std::vector<QPDFObjectHandle>& part8,
|
std::vector<QPDFObjectHandle>& part8,
|
||||||
std::vector<QPDFObjectHandle>& part9)
|
std::vector<QPDFObjectHandle>& part9)
|
||||||
{
|
{
|
||||||
qpdf.getLinearizedParts(object_stream_data,
|
qpdf.getLinearizedParts(
|
||||||
part4, part6, part7, part8, part9);
|
object_stream_data, part4, part6, part7, part8, part9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generateHintStream(
|
static void
|
||||||
|
generateHintStream(
|
||||||
QPDF& qpdf,
|
QPDF& qpdf,
|
||||||
std::map<int, QPDFXRefEntry> const& xref,
|
std::map<int, QPDFXRefEntry> const& xref,
|
||||||
std::map<int, qpdf_offset_t> const& lengths,
|
std::map<int, qpdf_offset_t> const& lengths,
|
||||||
std::map<int, int> const& obj_renumber,
|
std::map<int, int> const& obj_renumber,
|
||||||
PointerHolder<Buffer>& hint_stream,
|
PointerHolder<Buffer>& hint_stream,
|
||||||
int& S, int& O)
|
int& S,
|
||||||
|
int& O)
|
||||||
{
|
{
|
||||||
return qpdf.generateHintStream(xref, lengths, obj_renumber,
|
return qpdf.generateHintStream(
|
||||||
hint_stream, S, O);
|
xref, lengths, obj_renumber, hint_stream, S, O);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getObjectStreamData(QPDF& qpdf, std::map<int, int>& omap)
|
static void
|
||||||
|
getObjectStreamData(QPDF& qpdf, std::map<int, int>& omap)
|
||||||
{
|
{
|
||||||
qpdf.getObjectStreamData(omap);
|
qpdf.getObjectStreamData(omap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<QPDFObjGen> getCompressibleObjGens(QPDF& qpdf)
|
static std::vector<QPDFObjGen>
|
||||||
|
getCompressibleObjGens(QPDF& qpdf)
|
||||||
{
|
{
|
||||||
return qpdf.getCompressibleObjGens();
|
return qpdf.getCompressibleObjGens();
|
||||||
}
|
}
|
||||||
@ -704,13 +740,15 @@ class QPDF
|
|||||||
class Resolver
|
class Resolver
|
||||||
{
|
{
|
||||||
friend class QPDFObjectHandle;
|
friend class QPDFObjectHandle;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PointerHolder<QPDFObject> resolve(
|
static PointerHolder<QPDFObject>
|
||||||
QPDF* qpdf, int objid, int generation)
|
resolve(QPDF* qpdf, int objid, int generation)
|
||||||
{
|
{
|
||||||
return qpdf->resolve(objid, generation);
|
return qpdf->resolve(objid, generation);
|
||||||
}
|
}
|
||||||
static bool objectChanged(
|
static bool
|
||||||
|
objectChanged(
|
||||||
QPDF* qpdf, QPDFObjGen const& og, PointerHolder<QPDFObject>& oph)
|
QPDF* qpdf, QPDFObjGen const& og, PointerHolder<QPDFObject>& oph)
|
||||||
{
|
{
|
||||||
return qpdf->objectChanged(og, oph);
|
return qpdf->objectChanged(og, oph);
|
||||||
@ -723,10 +761,13 @@ class QPDF
|
|||||||
class StreamCopier
|
class StreamCopier
|
||||||
{
|
{
|
||||||
friend class QPDFObjectHandle;
|
friend class QPDFObjectHandle;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void copyStreamData(QPDF* qpdf,
|
static void
|
||||||
QPDFObjectHandle const& dest,
|
copyStreamData(
|
||||||
QPDFObjectHandle const& src)
|
QPDF* qpdf,
|
||||||
|
QPDFObjectHandle const& dest,
|
||||||
|
QPDFObjectHandle const& src)
|
||||||
{
|
{
|
||||||
qpdf->copyStreamData(dest, src);
|
qpdf->copyStreamData(dest, src);
|
||||||
}
|
}
|
||||||
@ -738,19 +779,18 @@ class QPDF
|
|||||||
class ParseGuard
|
class ParseGuard
|
||||||
{
|
{
|
||||||
friend class QPDFObjectHandle;
|
friend class QPDFObjectHandle;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ParseGuard(QPDF* qpdf) :
|
ParseGuard(QPDF* qpdf) :
|
||||||
qpdf(qpdf)
|
qpdf(qpdf)
|
||||||
{
|
{
|
||||||
if (qpdf)
|
if (qpdf) {
|
||||||
{
|
|
||||||
qpdf->inParse(true);
|
qpdf->inParse(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~ParseGuard()
|
~ParseGuard()
|
||||||
{
|
{
|
||||||
if (qpdf)
|
if (qpdf) {
|
||||||
{
|
|
||||||
qpdf->inParse(false);
|
qpdf->inParse(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -762,17 +802,29 @@ class QPDF
|
|||||||
class Pipe
|
class Pipe
|
||||||
{
|
{
|
||||||
friend class QPDF_Stream;
|
friend class QPDF_Stream;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool pipeStreamData(QPDF* qpdf, int objid, int generation,
|
static bool
|
||||||
qpdf_offset_t offset, size_t length,
|
pipeStreamData(
|
||||||
QPDFObjectHandle dict,
|
QPDF* qpdf,
|
||||||
Pipeline* pipeline,
|
int objid,
|
||||||
bool suppress_warnings,
|
int generation,
|
||||||
bool will_retry)
|
qpdf_offset_t offset,
|
||||||
|
size_t length,
|
||||||
|
QPDFObjectHandle dict,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
bool suppress_warnings,
|
||||||
|
bool will_retry)
|
||||||
{
|
{
|
||||||
return qpdf->pipeStreamData(
|
return qpdf->pipeStreamData(
|
||||||
objid, generation, offset, length, dict, pipeline,
|
objid,
|
||||||
suppress_warnings, will_retry);
|
generation,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
dict,
|
||||||
|
pipeline,
|
||||||
|
suppress_warnings,
|
||||||
|
will_retry);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
friend class Pipe;
|
friend class Pipe;
|
||||||
@ -788,9 +840,10 @@ class QPDF
|
|||||||
end_after_space(0)
|
end_after_space(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ObjCache(PointerHolder<QPDFObject> object,
|
ObjCache(
|
||||||
qpdf_offset_t end_before_space,
|
PointerHolder<QPDFObject> object,
|
||||||
qpdf_offset_t end_after_space) :
|
qpdf_offset_t end_before_space,
|
||||||
|
qpdf_offset_t end_after_space) :
|
||||||
object(object),
|
object(object),
|
||||||
end_before_space(end_before_space),
|
end_before_space(end_before_space),
|
||||||
end_after_space(end_after_space)
|
end_after_space(end_after_space)
|
||||||
@ -813,6 +866,7 @@ class QPDF
|
|||||||
class EncryptionParameters
|
class EncryptionParameters
|
||||||
{
|
{
|
||||||
friend class QPDF;
|
friend class QPDF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EncryptionParameters();
|
EncryptionParameters();
|
||||||
|
|
||||||
@ -839,6 +893,7 @@ class QPDF
|
|||||||
class ForeignStreamData
|
class ForeignStreamData
|
||||||
{
|
{
|
||||||
friend class QPDF;
|
friend class QPDF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ForeignStreamData(
|
ForeignStreamData(
|
||||||
PointerHolder<EncryptionParameters> encp,
|
PointerHolder<EncryptionParameters> encp,
|
||||||
@ -867,18 +922,21 @@ class QPDF
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual bool provideStreamData(
|
virtual bool provideStreamData(
|
||||||
int objid, int generation, Pipeline* pipeline,
|
int objid,
|
||||||
bool suppress_warnings, bool will_retry) override;
|
int generation,
|
||||||
void registerForeignStream(QPDFObjGen const& local_og,
|
Pipeline* pipeline,
|
||||||
QPDFObjectHandle foreign_stream);
|
bool suppress_warnings,
|
||||||
void registerForeignStream(QPDFObjGen const& local_og,
|
bool will_retry) override;
|
||||||
PointerHolder<ForeignStreamData>);
|
void registerForeignStream(
|
||||||
|
QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
|
||||||
|
void registerForeignStream(
|
||||||
|
QPDFObjGen const& local_og, PointerHolder<ForeignStreamData>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDF& destination_qpdf;
|
QPDF& destination_qpdf;
|
||||||
std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
|
std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
|
||||||
std::map<QPDFObjGen,
|
std::map<QPDFObjGen, PointerHolder<ForeignStreamData>>
|
||||||
PointerHolder<ForeignStreamData> > foreign_stream_data;
|
foreign_stream_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringDecrypter: public QPDFObjectHandle::StringDecrypter
|
class StringDecrypter: public QPDFObjectHandle::StringDecrypter
|
||||||
@ -911,6 +969,7 @@ class QPDF
|
|||||||
{
|
{
|
||||||
this->qpdf->m->resolving.erase(og);
|
this->qpdf->m->resolving.erase(og);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDF* qpdf;
|
QPDF* qpdf;
|
||||||
QPDFObjGen og;
|
QPDFObjGen og;
|
||||||
@ -922,56 +981,72 @@ class QPDF
|
|||||||
void setTrailer(QPDFObjectHandle obj);
|
void setTrailer(QPDFObjectHandle obj);
|
||||||
void read_xref(qpdf_offset_t offset);
|
void read_xref(qpdf_offset_t offset);
|
||||||
void reconstruct_xref(QPDFExc& e);
|
void reconstruct_xref(QPDFExc& e);
|
||||||
bool parse_xrefFirst(std::string const& line,
|
bool
|
||||||
int& obj, int& num, int& bytes);
|
parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes);
|
||||||
bool parse_xrefEntry(std::string const& line,
|
bool parse_xrefEntry(
|
||||||
qpdf_offset_t& f1, int& f2, char& type);
|
std::string const& line, qpdf_offset_t& f1, int& f2, char& type);
|
||||||
qpdf_offset_t read_xrefTable(qpdf_offset_t offset);
|
qpdf_offset_t read_xrefTable(qpdf_offset_t offset);
|
||||||
qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
|
qpdf_offset_t read_xrefStream(qpdf_offset_t offset);
|
||||||
qpdf_offset_t processXRefStream(
|
qpdf_offset_t
|
||||||
qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
|
processXRefStream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream);
|
||||||
void insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2,
|
void insertXrefEntry(
|
||||||
bool overwrite = false);
|
int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
|
||||||
void setLastObjectDescription(std::string const& description,
|
void setLastObjectDescription(
|
||||||
int objid, int generation);
|
std::string const& description, int objid, int generation);
|
||||||
QPDFObjectHandle readObject(
|
QPDFObjectHandle readObject(
|
||||||
PointerHolder<InputSource>, std::string const& description,
|
PointerHolder<InputSource>,
|
||||||
int objid, int generation, bool in_object_stream);
|
std::string const& description,
|
||||||
|
int objid,
|
||||||
|
int generation,
|
||||||
|
bool in_object_stream);
|
||||||
size_t recoverStreamLength(
|
size_t recoverStreamLength(
|
||||||
PointerHolder<InputSource> input, int objid, int generation,
|
PointerHolder<InputSource> input,
|
||||||
|
int objid,
|
||||||
|
int generation,
|
||||||
qpdf_offset_t stream_offset);
|
qpdf_offset_t stream_offset);
|
||||||
QPDFTokenizer::Token readToken(PointerHolder<InputSource>,
|
QPDFTokenizer::Token
|
||||||
size_t max_len = 0);
|
readToken(PointerHolder<InputSource>, size_t max_len = 0);
|
||||||
|
|
||||||
QPDFObjectHandle readObjectAtOffset(
|
QPDFObjectHandle readObjectAtOffset(
|
||||||
bool attempt_recovery,
|
bool attempt_recovery,
|
||||||
qpdf_offset_t offset, std::string const& description,
|
qpdf_offset_t offset,
|
||||||
int exp_objid, int exp_generation,
|
std::string const& description,
|
||||||
int& act_objid, int& act_generation);
|
int exp_objid,
|
||||||
|
int exp_generation,
|
||||||
|
int& act_objid,
|
||||||
|
int& act_generation);
|
||||||
bool objectChanged(QPDFObjGen const& og, PointerHolder<QPDFObject>& oph);
|
bool objectChanged(QPDFObjGen const& og, PointerHolder<QPDFObject>& oph);
|
||||||
PointerHolder<QPDFObject> resolve(int objid, int generation);
|
PointerHolder<QPDFObject> resolve(int objid, int generation);
|
||||||
void resolveObjectsInStream(int obj_stream_number);
|
void resolveObjectsInStream(int obj_stream_number);
|
||||||
void stopOnError(std::string const& message);
|
void stopOnError(std::string const& message);
|
||||||
|
|
||||||
// Calls finish() on the pipeline when done but does not delete it
|
// Calls finish() on the pipeline when done but does not delete it
|
||||||
bool pipeStreamData(int objid, int generation,
|
bool pipeStreamData(
|
||||||
qpdf_offset_t offset, size_t length,
|
int objid,
|
||||||
QPDFObjectHandle dict,
|
int generation,
|
||||||
Pipeline* pipeline,
|
qpdf_offset_t offset,
|
||||||
bool suppress_warnings,
|
size_t length,
|
||||||
bool will_retry);
|
QPDFObjectHandle dict,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
bool suppress_warnings,
|
||||||
|
bool will_retry);
|
||||||
bool pipeForeignStreamData(
|
bool pipeForeignStreamData(
|
||||||
PointerHolder<ForeignStreamData>,
|
PointerHolder<ForeignStreamData>,
|
||||||
Pipeline*, bool suppress_warnings, bool will_retry);
|
Pipeline*,
|
||||||
static bool pipeStreamData(PointerHolder<QPDF::EncryptionParameters> encp,
|
bool suppress_warnings,
|
||||||
PointerHolder<InputSource> file,
|
bool will_retry);
|
||||||
QPDF& qpdf_for_warning,
|
static bool pipeStreamData(
|
||||||
int objid, int generation,
|
PointerHolder<QPDF::EncryptionParameters> encp,
|
||||||
qpdf_offset_t offset, size_t length,
|
PointerHolder<InputSource> file,
|
||||||
QPDFObjectHandle dict,
|
QPDF& qpdf_for_warning,
|
||||||
Pipeline* pipeline,
|
int objid,
|
||||||
bool suppress_warnings,
|
int generation,
|
||||||
bool will_retry);
|
qpdf_offset_t offset,
|
||||||
|
size_t length,
|
||||||
|
QPDFObjectHandle dict,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
bool suppress_warnings,
|
||||||
|
bool will_retry);
|
||||||
|
|
||||||
// For QPDFWriter:
|
// For QPDFWriter:
|
||||||
|
|
||||||
@ -985,11 +1060,13 @@ class QPDF
|
|||||||
std::vector<QPDFObjectHandle>& part8,
|
std::vector<QPDFObjectHandle>& part8,
|
||||||
std::vector<QPDFObjectHandle>& part9);
|
std::vector<QPDFObjectHandle>& part9);
|
||||||
|
|
||||||
void generateHintStream(std::map<int, QPDFXRefEntry> const& xref,
|
void generateHintStream(
|
||||||
std::map<int, qpdf_offset_t> const& lengths,
|
std::map<int, QPDFXRefEntry> const& xref,
|
||||||
std::map<int, int> const& obj_renumber,
|
std::map<int, qpdf_offset_t> const& lengths,
|
||||||
PointerHolder<Buffer>& hint_stream,
|
std::map<int, int> const& obj_renumber,
|
||||||
int& S, int& O);
|
PointerHolder<Buffer>& hint_stream,
|
||||||
|
int& S,
|
||||||
|
int& O);
|
||||||
|
|
||||||
// Map object to object stream that contains it
|
// Map object to object stream that contains it
|
||||||
void getObjectStreamData(std::map<int, int>&);
|
void getObjectStreamData(std::map<int, int>&);
|
||||||
@ -1000,45 +1077,51 @@ class QPDF
|
|||||||
|
|
||||||
// methods to support page handling
|
// methods to support page handling
|
||||||
|
|
||||||
void getAllPagesInternal(QPDFObjectHandle cur_pages,
|
void getAllPagesInternal(
|
||||||
std::vector<QPDFObjectHandle>& result,
|
QPDFObjectHandle cur_pages,
|
||||||
std::set<QPDFObjGen>& visited,
|
std::vector<QPDFObjectHandle>& result,
|
||||||
std::set<QPDFObjGen>& seen);
|
std::set<QPDFObjGen>& visited,
|
||||||
|
std::set<QPDFObjGen>& seen);
|
||||||
void insertPage(QPDFObjectHandle newpage, int pos);
|
void insertPage(QPDFObjectHandle newpage, int pos);
|
||||||
void flattenPagesTree();
|
void flattenPagesTree();
|
||||||
void insertPageobjToPage(QPDFObjectHandle const& obj, int pos,
|
void insertPageobjToPage(
|
||||||
bool check_duplicate);
|
QPDFObjectHandle const& obj, int pos, bool check_duplicate);
|
||||||
|
|
||||||
// methods to support encryption -- implemented in QPDF_encryption.cc
|
// methods to support encryption -- implemented in QPDF_encryption.cc
|
||||||
static encryption_method_e interpretCF(
|
static encryption_method_e
|
||||||
PointerHolder<EncryptionParameters> encp, QPDFObjectHandle);
|
interpretCF(PointerHolder<EncryptionParameters> encp, QPDFObjectHandle);
|
||||||
void initializeEncryption();
|
void initializeEncryption();
|
||||||
static std::string getKeyForObject(
|
static std::string getKeyForObject(
|
||||||
PointerHolder<EncryptionParameters> encp,
|
PointerHolder<EncryptionParameters> encp,
|
||||||
int objid, int generation, bool use_aes);
|
int objid,
|
||||||
|
int generation,
|
||||||
|
bool use_aes);
|
||||||
void decryptString(std::string&, int objid, int generation);
|
void decryptString(std::string&, int objid, int generation);
|
||||||
static std::string compute_encryption_key_from_password(
|
static std::string compute_encryption_key_from_password(
|
||||||
std::string const& password, EncryptionData const& data);
|
std::string const& password, EncryptionData const& data);
|
||||||
static std::string recover_encryption_key_with_password(
|
static std::string recover_encryption_key_with_password(
|
||||||
std::string const& password, EncryptionData const& data);
|
std::string const& password, EncryptionData const& data);
|
||||||
static std::string recover_encryption_key_with_password(
|
static std::string recover_encryption_key_with_password(
|
||||||
std::string const& password, EncryptionData const& data,
|
std::string const& password,
|
||||||
|
EncryptionData const& data,
|
||||||
bool& perms_valid);
|
bool& perms_valid);
|
||||||
static void decryptStream(
|
static void decryptStream(
|
||||||
PointerHolder<EncryptionParameters> encp,
|
PointerHolder<EncryptionParameters> encp,
|
||||||
PointerHolder<InputSource> file,
|
PointerHolder<InputSource> file,
|
||||||
QPDF& qpdf_for_warning, Pipeline*& pipeline,
|
QPDF& qpdf_for_warning,
|
||||||
int objid, int generation,
|
Pipeline*& pipeline,
|
||||||
|
int objid,
|
||||||
|
int generation,
|
||||||
QPDFObjectHandle& stream_dict,
|
QPDFObjectHandle& stream_dict,
|
||||||
std::vector<std::shared_ptr<Pipeline>>& heap);
|
std::vector<std::shared_ptr<Pipeline>>& heap);
|
||||||
|
|
||||||
// Methods to support object copying
|
// Methods to support object copying
|
||||||
void reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
|
void
|
||||||
bool top);
|
reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
||||||
QPDFObjectHandle replaceForeignIndirectObjects(
|
QPDFObjectHandle replaceForeignIndirectObjects(
|
||||||
QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
|
||||||
void copyStreamData(
|
void
|
||||||
QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
|
copyStreamData(QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
|
||||||
|
|
||||||
// Linearization Hint table structures.
|
// Linearization Hint table structures.
|
||||||
// Naming conventions:
|
// Naming conventions:
|
||||||
@ -1065,14 +1148,14 @@ class QPDF
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int delta_nobjects; // 1
|
int delta_nobjects; // 1
|
||||||
qpdf_offset_t delta_page_length; // 2
|
qpdf_offset_t delta_page_length; // 2
|
||||||
int nshared_objects; // 3
|
int nshared_objects; // 3
|
||||||
// vectors' sizes = nshared_objects
|
// vectors' sizes = nshared_objects
|
||||||
std::vector<int> shared_identifiers; // 4
|
std::vector<int> shared_identifiers; // 4
|
||||||
std::vector<int> shared_numerators; // 5
|
std::vector<int> shared_numerators; // 5
|
||||||
qpdf_offset_t delta_content_offset; // 6
|
qpdf_offset_t delta_content_offset; // 6
|
||||||
qpdf_offset_t delta_content_length; // 7
|
qpdf_offset_t delta_content_length; // 7
|
||||||
};
|
};
|
||||||
|
|
||||||
// PDF 1.4: Table F.3
|
// PDF 1.4: Table F.3
|
||||||
@ -1095,19 +1178,19 @@ class QPDF
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int min_nobjects; // 1
|
int min_nobjects; // 1
|
||||||
qpdf_offset_t first_page_offset; // 2
|
qpdf_offset_t first_page_offset; // 2
|
||||||
int nbits_delta_nobjects; // 3
|
int nbits_delta_nobjects; // 3
|
||||||
int min_page_length; // 4
|
int min_page_length; // 4
|
||||||
int nbits_delta_page_length; // 5
|
int nbits_delta_page_length; // 5
|
||||||
int min_content_offset; // 6
|
int min_content_offset; // 6
|
||||||
int nbits_delta_content_offset; // 7
|
int nbits_delta_content_offset; // 7
|
||||||
int min_content_length; // 8
|
int min_content_length; // 8
|
||||||
int nbits_delta_content_length; // 9
|
int nbits_delta_content_length; // 9
|
||||||
int nbits_nshared_objects; // 10
|
int nbits_nshared_objects; // 10
|
||||||
int nbits_shared_identifier; // 11
|
int nbits_shared_identifier; // 11
|
||||||
int nbits_shared_numerator; // 12
|
int nbits_shared_numerator; // 12
|
||||||
int shared_denominator; // 13
|
int shared_denominator; // 13
|
||||||
// vector size is npages
|
// vector size is npages
|
||||||
std::vector<HPageOffsetEntry> entries;
|
std::vector<HPageOffsetEntry> entries;
|
||||||
};
|
};
|
||||||
@ -1123,9 +1206,9 @@ class QPDF
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Item 3 is a 128-bit signature (unsupported by Acrobat)
|
// Item 3 is a 128-bit signature (unsupported by Acrobat)
|
||||||
int delta_group_length; // 1
|
int delta_group_length; // 1
|
||||||
int signature_present; // 2 -- always 0
|
int signature_present; // 2 -- always 0
|
||||||
int nobjects_minus_one; // 4 -- always 0
|
int nobjects_minus_one; // 4 -- always 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// PDF 1.4: Table F.5
|
// PDF 1.4: Table F.5
|
||||||
@ -1142,13 +1225,13 @@ class QPDF
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int first_shared_obj; // 1
|
int first_shared_obj; // 1
|
||||||
qpdf_offset_t first_shared_offset; // 2
|
qpdf_offset_t first_shared_offset; // 2
|
||||||
int nshared_first_page; // 3
|
int nshared_first_page; // 3
|
||||||
int nshared_total; // 4
|
int nshared_total; // 4
|
||||||
int nbits_nobjects; // 5
|
int nbits_nobjects; // 5
|
||||||
int min_group_length; // 6
|
int min_group_length; // 6
|
||||||
int nbits_delta_group_length; // 7
|
int nbits_delta_group_length; // 7
|
||||||
// vector size is nshared_total
|
// vector size is nshared_total
|
||||||
std::vector<HSharedObjectEntry> entries;
|
std::vector<HSharedObjectEntry> entries;
|
||||||
};
|
};
|
||||||
@ -1164,10 +1247,10 @@ class QPDF
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int first_object; // 1
|
int first_object; // 1
|
||||||
qpdf_offset_t first_object_offset; // 2
|
qpdf_offset_t first_object_offset; // 2
|
||||||
int nobjects; // 3
|
int nobjects; // 3
|
||||||
int group_length; // 4
|
int group_length; // 4
|
||||||
};
|
};
|
||||||
|
|
||||||
// Other linearization data structures
|
// Other linearization data structures
|
||||||
@ -1261,15 +1344,13 @@ class QPDF
|
|||||||
|
|
||||||
// No need for CHGeneric -- HGeneric is fine as is.
|
// No need for CHGeneric -- HGeneric is fine as is.
|
||||||
|
|
||||||
|
|
||||||
// Data structures to support optimization -- implemented in
|
// Data structures to support optimization -- implemented in
|
||||||
// QPDF_optimization.cc
|
// QPDF_optimization.cc
|
||||||
|
|
||||||
class ObjUser
|
class ObjUser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum user_e
|
enum user_e {
|
||||||
{
|
|
||||||
ou_bad,
|
ou_bad,
|
||||||
ou_page,
|
ou_page,
|
||||||
ou_thumb,
|
ou_thumb,
|
||||||
@ -1293,8 +1374,8 @@ class QPDF
|
|||||||
bool operator<(ObjUser const&) const;
|
bool operator<(ObjUser const&) const;
|
||||||
|
|
||||||
user_e ou_type;
|
user_e ou_type;
|
||||||
int pageno; // if ou_page;
|
int pageno; // if ou_page;
|
||||||
std::string key; // if ou_trailer_key or ou_root_key
|
std::string key; // if ou_trailer_key or ou_root_key
|
||||||
};
|
};
|
||||||
|
|
||||||
class PatternFinder: public InputSource::Finder
|
class PatternFinder: public InputSource::Finder
|
||||||
@ -1308,7 +1389,8 @@ class QPDF
|
|||||||
virtual ~PatternFinder()
|
virtual ~PatternFinder()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual bool check()
|
virtual bool
|
||||||
|
check()
|
||||||
{
|
{
|
||||||
return (this->qpdf.*checker)();
|
return (this->qpdf.*checker)();
|
||||||
}
|
}
|
||||||
@ -1328,8 +1410,8 @@ class QPDF
|
|||||||
void readLinearizationData();
|
void readLinearizationData();
|
||||||
bool checkLinearizationInternal();
|
bool checkLinearizationInternal();
|
||||||
void dumpLinearizationDataInternal();
|
void dumpLinearizationDataInternal();
|
||||||
QPDFObjectHandle readHintStream(
|
QPDFObjectHandle
|
||||||
Pipeline&, qpdf_offset_t offset, size_t length);
|
readHintStream(Pipeline&, qpdf_offset_t offset, size_t length);
|
||||||
void readHPageOffset(BitStream);
|
void readHPageOffset(BitStream);
|
||||||
void readHSharedObject(BitStream);
|
void readHSharedObject(BitStream);
|
||||||
void readHGeneric(BitStream, HGeneric&);
|
void readHGeneric(BitStream, HGeneric&);
|
||||||
@ -1337,30 +1419,32 @@ class QPDF
|
|||||||
qpdf_offset_t getLinearizationOffset(QPDFObjGen const&);
|
qpdf_offset_t getLinearizationOffset(QPDFObjGen const&);
|
||||||
QPDFObjectHandle getUncompressedObject(
|
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,
|
int lengthNextN(int first_object, int n, std::list<std::string>& errors);
|
||||||
std::list<std::string>& errors);
|
void checkHPageOffset(
|
||||||
void checkHPageOffset(std::list<std::string>& errors,
|
std::list<std::string>& errors,
|
||||||
std::list<std::string>& warnings,
|
std::list<std::string>& warnings,
|
||||||
std::vector<QPDFObjectHandle> const& pages,
|
std::vector<QPDFObjectHandle> const& pages,
|
||||||
std::map<int, int>& idx_to_obj);
|
std::map<int, int>& idx_to_obj);
|
||||||
void checkHSharedObject(std::list<std::string>& warnings,
|
void checkHSharedObject(
|
||||||
std::list<std::string>& errors,
|
std::list<std::string>& warnings,
|
||||||
std::vector<QPDFObjectHandle> const& pages,
|
std::list<std::string>& errors,
|
||||||
std::map<int, int>& idx_to_obj);
|
std::vector<QPDFObjectHandle> const& pages,
|
||||||
|
std::map<int, int>& idx_to_obj);
|
||||||
void checkHOutlines(std::list<std::string>& warnings);
|
void checkHOutlines(std::list<std::string>& warnings);
|
||||||
void dumpHPageOffset();
|
void dumpHPageOffset();
|
||||||
void dumpHSharedObject();
|
void dumpHSharedObject();
|
||||||
void dumpHGeneric(HGeneric&);
|
void dumpHGeneric(HGeneric&);
|
||||||
qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
|
qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
|
||||||
QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);
|
QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);
|
||||||
void calculateLinearizationData(
|
void
|
||||||
std::map<int, int> const& object_stream_data);
|
calculateLinearizationData(std::map<int, int> const& object_stream_data);
|
||||||
void pushOutlinesToPart(
|
void pushOutlinesToPart(
|
||||||
std::vector<QPDFObjectHandle>& part,
|
std::vector<QPDFObjectHandle>& part,
|
||||||
std::set<QPDFObjGen>& lc_outlines,
|
std::set<QPDFObjGen>& lc_outlines,
|
||||||
std::map<int, int> const& object_stream_data);
|
std::map<int, int> const& object_stream_data);
|
||||||
int outputLengthNextN(
|
int outputLengthNextN(
|
||||||
int in_object, int n,
|
int in_object,
|
||||||
|
int n,
|
||||||
std::map<int, qpdf_offset_t> const& lengths,
|
std::map<int, qpdf_offset_t> const& lengths,
|
||||||
std::map<int, int> const& obj_renumber);
|
std::map<int, int> const& obj_renumber);
|
||||||
void calculateHPageOffset(
|
void calculateHPageOffset(
|
||||||
@ -1379,37 +1463,46 @@ class QPDF
|
|||||||
void writeHSharedObject(BitWriter&);
|
void writeHSharedObject(BitWriter&);
|
||||||
void writeHGeneric(BitWriter&, HGeneric&);
|
void writeHGeneric(BitWriter&, HGeneric&);
|
||||||
|
|
||||||
|
|
||||||
// Methods to support optimization
|
// Methods to support optimization
|
||||||
|
|
||||||
void pushInheritedAttributesToPage(bool allow_changes,
|
void
|
||||||
bool warn_skipped_keys);
|
pushInheritedAttributesToPage(bool allow_changes, bool warn_skipped_keys);
|
||||||
void pushInheritedAttributesToPageInternal(
|
void pushInheritedAttributesToPageInternal(
|
||||||
QPDFObjectHandle,
|
QPDFObjectHandle,
|
||||||
std::map<std::string, std::vector<QPDFObjectHandle> >&,
|
std::map<std::string, std::vector<QPDFObjectHandle>>&,
|
||||||
std::vector<QPDFObjectHandle>& all_pages,
|
std::vector<QPDFObjectHandle>& all_pages,
|
||||||
bool allow_changes, bool warn_skipped_keys,
|
bool allow_changes,
|
||||||
|
bool warn_skipped_keys,
|
||||||
std::set<QPDFObjGen>& visited);
|
std::set<QPDFObjGen>& visited);
|
||||||
void updateObjectMaps(
|
void updateObjectMaps(
|
||||||
ObjUser const& ou, QPDFObjectHandle oh,
|
ObjUser const& ou,
|
||||||
|
QPDFObjectHandle oh,
|
||||||
std::function<int(QPDFObjectHandle&)> skip_stream_parameters);
|
std::function<int(QPDFObjectHandle&)> skip_stream_parameters);
|
||||||
void updateObjectMapsInternal(
|
void updateObjectMapsInternal(
|
||||||
ObjUser const& ou, QPDFObjectHandle oh,
|
ObjUser const& ou,
|
||||||
|
QPDFObjectHandle oh,
|
||||||
std::function<int(QPDFObjectHandle&)> skip_stream_parameters,
|
std::function<int(QPDFObjectHandle&)> skip_stream_parameters,
|
||||||
std::set<QPDFObjGen>& visited, bool top,
|
std::set<QPDFObjGen>& visited,
|
||||||
|
bool top,
|
||||||
int depth);
|
int depth);
|
||||||
void filterCompressedObjects(std::map<int, int> const& object_stream_data);
|
void filterCompressedObjects(std::map<int, int> const& object_stream_data);
|
||||||
|
|
||||||
// Type conversion helper methods
|
// Type conversion helper methods
|
||||||
template<typename T> static qpdf_offset_t toO(T const& i)
|
template <typename T>
|
||||||
|
static qpdf_offset_t
|
||||||
|
toO(T const& i)
|
||||||
{
|
{
|
||||||
return QIntC::to_offset(i);
|
return QIntC::to_offset(i);
|
||||||
}
|
}
|
||||||
template<typename T> static size_t toS(T const& i)
|
template <typename T>
|
||||||
|
static size_t
|
||||||
|
toS(T const& i)
|
||||||
{
|
{
|
||||||
return QIntC::to_size(i);
|
return QIntC::to_size(i);
|
||||||
}
|
}
|
||||||
template<typename T> static int toI(T const& i)
|
template <typename T>
|
||||||
|
static int
|
||||||
|
toI(T const& i)
|
||||||
{
|
{
|
||||||
return QIntC::to_int(i);
|
return QIntC::to_int(i);
|
||||||
}
|
}
|
||||||
@ -1490,8 +1583,8 @@ class QPDF
|
|||||||
std::vector<QPDFObjectHandle> part9;
|
std::vector<QPDFObjectHandle> part9;
|
||||||
|
|
||||||
// Optimization data
|
// Optimization data
|
||||||
std::map<ObjUser, std::set<QPDFObjGen> > obj_user_to_objects;
|
std::map<ObjUser, std::set<QPDFObjGen>> obj_user_to_objects;
|
||||||
std::map<QPDFObjGen, std::set<ObjUser> > object_to_obj_users;
|
std::map<QPDFObjGen, std::set<ObjUser>> object_to_obj_users;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Keep all member variables inside the Members object, which we
|
// Keep all member variables inside the Members object, which we
|
||||||
|
@ -67,7 +67,6 @@
|
|||||||
// the "/AcroForm" field entry until you find the annotation
|
// the "/AcroForm" field entry until you find the annotation
|
||||||
// dictionary.
|
// dictionary.
|
||||||
|
|
||||||
|
|
||||||
#include <qpdf/QPDFDocumentHelper.hh>
|
#include <qpdf/QPDFDocumentHelper.hh>
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
@ -144,8 +143,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
// information to be accurate, any changes to field names must be
|
// information to be accurate, any changes to field names must be
|
||||||
// done through setFormFieldName() above.
|
// done through setFormFieldName() above.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::set<QPDFObjGen>
|
std::set<QPDFObjGen> getFieldsWithQualifiedName(std::string const& name);
|
||||||
getFieldsWithQualifiedName(std::string const& name);
|
|
||||||
|
|
||||||
// Return the annotations associated with a terminal field. Note
|
// Return the annotations associated with a terminal field. Note
|
||||||
// that in the case of a field having a single annotation, the
|
// that in the case of a field having a single annotation, the
|
||||||
@ -153,17 +151,17 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
// object for the field.
|
// object for the field.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::vector<QPDFAnnotationObjectHelper>
|
std::vector<QPDFAnnotationObjectHelper>
|
||||||
getAnnotationsForField(QPDFFormFieldObjectHelper);
|
getAnnotationsForField(QPDFFormFieldObjectHelper);
|
||||||
|
|
||||||
// Return annotations of subtype /Widget for a page.
|
// Return annotations of subtype /Widget for a page.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::vector<QPDFAnnotationObjectHelper>
|
std::vector<QPDFAnnotationObjectHelper>
|
||||||
getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
||||||
|
|
||||||
// Return top-level form fields for a page.
|
// Return top-level form fields for a page.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::vector<QPDFFormFieldObjectHelper>
|
std::vector<QPDFFormFieldObjectHelper>
|
||||||
getFormFieldsForPage(QPDFPageObjectHelper);
|
getFormFieldsForPage(QPDFPageObjectHelper);
|
||||||
|
|
||||||
// Return the terminal field that is associated with this
|
// Return the terminal field that is associated with this
|
||||||
// annotation. If the annotation dictionary is merged with the
|
// annotation. If the annotation dictionary is merged with the
|
||||||
@ -173,8 +171,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
// not be an associated field, and this method will return a
|
// not be an associated field, and this method will return a
|
||||||
// helper associated with a null object (isNull() == true).
|
// helper associated with a null object (isNull() == true).
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFFormFieldObjectHelper
|
QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper);
|
||||||
getFieldForAnnotation(QPDFAnnotationObjectHelper);
|
|
||||||
|
|
||||||
// Return the current value of /NeedAppearances. If
|
// Return the current value of /NeedAppearances. If
|
||||||
// /NeedAppearances is missing, return false as that is how PDF
|
// /NeedAppearances is missing, return false as that is how PDF
|
||||||
@ -260,30 +257,33 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
// happens with qpdf --split-pages.
|
// happens with qpdf --split-pages.
|
||||||
[[deprecated("Use fixCopiedAnnotations instead")]]
|
[[deprecated("Use fixCopiedAnnotations instead")]]
|
||||||
// ABI: delete this method
|
// ABI: delete this method
|
||||||
QPDF_DLL
|
QPDF_DLL void
|
||||||
void copyFieldsFromForeignPage(
|
copyFieldsFromForeignPage(
|
||||||
QPDFPageObjectHelper foreign_page,
|
QPDFPageObjectHelper foreign_page,
|
||||||
QPDFAcroFormDocumentHelper& foreign_afdh,
|
QPDFAcroFormDocumentHelper& foreign_afdh,
|
||||||
std::vector<QPDFObjectHandle>* copied_fields = nullptr);
|
std::vector<QPDFObjectHandle>* copied_fields = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void analyze();
|
void analyze();
|
||||||
void traverseField(QPDFObjectHandle field,
|
void traverseField(
|
||||||
QPDFObjectHandle parent,
|
QPDFObjectHandle field,
|
||||||
int depth, std::set<QPDFObjGen>& visited);
|
QPDFObjectHandle parent,
|
||||||
|
int depth,
|
||||||
|
std::set<QPDFObjGen>& visited);
|
||||||
QPDFObjectHandle getOrCreateAcroForm();
|
QPDFObjectHandle getOrCreateAcroForm();
|
||||||
void adjustInheritedFields(
|
void adjustInheritedFields(
|
||||||
QPDFObjectHandle obj,
|
QPDFObjectHandle obj,
|
||||||
bool override_da, std::string const& from_default_da,
|
bool override_da,
|
||||||
bool override_q, int from_default_q);
|
std::string const& from_default_da,
|
||||||
|
bool override_q,
|
||||||
|
int from_default_q);
|
||||||
void adjustDefaultAppearances(
|
void adjustDefaultAppearances(
|
||||||
QPDFObjectHandle obj,
|
QPDFObjectHandle obj,
|
||||||
std::map<std::string,
|
std::map<std::string, std::map<std::string, std::string>> const&
|
||||||
std::map<std::string, std::string>> const& dr_map);
|
dr_map);
|
||||||
void adjustAppearanceStream(
|
void adjustAppearanceStream(
|
||||||
QPDFObjectHandle stream,
|
QPDFObjectHandle stream,
|
||||||
std::map<std::string,
|
std::map<std::string, std::map<std::string, std::string>> dr_map);
|
||||||
std::map<std::string, std::string>> dr_map);
|
|
||||||
|
|
||||||
class Members
|
class Members
|
||||||
{
|
{
|
||||||
@ -298,9 +298,8 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
|||||||
Members(Members const&);
|
Members(Members const&);
|
||||||
|
|
||||||
bool cache_valid;
|
bool cache_valid;
|
||||||
std::map<QPDFObjGen,
|
std::map<QPDFObjGen, std::vector<QPDFAnnotationObjectHelper>>
|
||||||
std::vector<QPDFAnnotationObjectHelper>
|
field_to_annotations;
|
||||||
> field_to_annotations;
|
|
||||||
std::map<QPDFObjGen, QPDFFormFieldObjectHelper> annotation_to_field;
|
std::map<QPDFObjGen, QPDFFormFieldObjectHelper> annotation_to_field;
|
||||||
std::map<QPDFObjGen, std::string> field_to_name;
|
std::map<QPDFObjGen, std::string> field_to_name;
|
||||||
std::map<std::string, std::set<QPDFObjGen>> name_to_fields;
|
std::map<std::string, std::set<QPDFObjGen>> name_to_fields;
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#ifndef QPDFANNOTATIONOBJECTHELPER_HH
|
#ifndef QPDFANNOTATIONOBJECTHELPER_HH
|
||||||
#define QPDFANNOTATIONOBJECTHELPER_HH
|
#define QPDFANNOTATIONOBJECTHELPER_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHelper.hh>
|
|
||||||
#include <qpdf/Constants.h>
|
#include <qpdf/Constants.h>
|
||||||
|
#include <qpdf/QPDFObjectHelper.hh>
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ class QPDFAnnotationObjectHelper: public QPDFObjectHelper
|
|||||||
// which appearance stream is desired. If not specified, the
|
// which appearance stream is desired. If not specified, the
|
||||||
// appearance state in "/AS" will used.
|
// appearance state in "/AS" will used.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle getAppearanceStream(std::string const& which,
|
QPDFObjectHandle getAppearanceStream(
|
||||||
std::string const& state = "");
|
std::string const& which, std::string const& state = "");
|
||||||
|
|
||||||
// Generate text suitable for addition to the containing page's
|
// Generate text suitable for addition to the containing page's
|
||||||
// content stream that draws this annotation's appearance stream
|
// content stream that draws this annotation's appearance stream
|
||||||
@ -96,7 +96,8 @@ class QPDFAnnotationObjectHelper: public QPDFObjectHelper
|
|||||||
// preparing to print.
|
// preparing to print.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string getPageContentForAppearance(
|
std::string getPageContentForAppearance(
|
||||||
std::string const& name, int rotate,
|
std::string const& name,
|
||||||
|
int rotate,
|
||||||
int required_flags = 0,
|
int required_flags = 0,
|
||||||
int forbidden_flags = an_invisible | an_hidden);
|
int forbidden_flags = an_invisible | an_hidden);
|
||||||
|
|
||||||
|
@ -77,19 +77,22 @@ class QPDF_DLL_CLASS QPDFCryptoImpl
|
|||||||
virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0;
|
virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0;
|
||||||
// out_data = 0 means to encrypt/decrypt in place
|
// out_data = 0 means to encrypt/decrypt in place
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void RC4_process(unsigned char* in_data, size_t len,
|
virtual void RC4_process(
|
||||||
unsigned char* out_data = 0) = 0;
|
unsigned char* in_data, size_t len, unsigned char* out_data = 0) = 0;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void RC4_finalize() = 0;
|
virtual void RC4_finalize() = 0;
|
||||||
|
|
||||||
static size_t constexpr rijndael_buf_size = 16;
|
static size_t constexpr rijndael_buf_size = 16;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void rijndael_init(
|
virtual void rijndael_init(
|
||||||
bool encrypt, unsigned char const* key_data, size_t key_len,
|
bool encrypt,
|
||||||
bool cbc_mode, unsigned char* cbc_block) = 0;
|
unsigned char const* key_data,
|
||||||
|
size_t key_len,
|
||||||
|
bool cbc_mode,
|
||||||
|
unsigned char* cbc_block) = 0;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void rijndael_process(
|
virtual void
|
||||||
unsigned char* in_data, unsigned char* out_data) = 0;
|
rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void rijndael_finalize() = 0;
|
virtual void rijndael_finalize() = 0;
|
||||||
};
|
};
|
||||||
|
@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/QPDFCryptoImpl.hh>
|
#include <qpdf/QPDFCryptoImpl.hh>
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <memory>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// This class is part of qpdf's pluggable crypto provider support.
|
// This class is part of qpdf's pluggable crypto provider support.
|
||||||
// Most users won't need to know or care about this class, but you can
|
// Most users won't need to know or care about this class, but you can
|
||||||
@ -38,7 +38,6 @@
|
|||||||
class QPDFCryptoProvider
|
class QPDFCryptoProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Methods for getting and registering crypto implementations.
|
// Methods for getting and registering crypto implementations.
|
||||||
// These methods are not thread-safe.
|
// These methods are not thread-safe.
|
||||||
|
|
||||||
@ -50,15 +49,13 @@ class QPDFCryptoProvider
|
|||||||
// Return an instance of the crypto provider registered using the
|
// Return an instance of the crypto provider registered using the
|
||||||
// given name.
|
// given name.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static std::shared_ptr<QPDFCryptoImpl>
|
static std::shared_ptr<QPDFCryptoImpl> getImpl(std::string const& name);
|
||||||
getImpl(std::string const& name);
|
|
||||||
|
|
||||||
// Register the given type (T) as a crypto implementation. T must
|
// Register the given type (T) as a crypto implementation. T must
|
||||||
// be derived from QPDFCryptoImpl and must have a constructor that
|
// be derived from QPDFCryptoImpl and must have a constructor that
|
||||||
// takes no arguments.
|
// takes no arguments.
|
||||||
template<typename T>
|
template <typename T>
|
||||||
QPDF_DLL
|
QPDF_DLL static void registerImpl(std::string const& name);
|
||||||
static void registerImpl(std::string const& name);
|
|
||||||
|
|
||||||
// Set the crypto provider registered with the given name as the
|
// Set the crypto provider registered with the given name as the
|
||||||
// default crypto implementation.
|
// default crypto implementation.
|
||||||
@ -83,7 +80,7 @@ class QPDFCryptoProvider
|
|||||||
|
|
||||||
std::shared_ptr<QPDFCryptoImpl>
|
std::shared_ptr<QPDFCryptoImpl>
|
||||||
getImpl_internal(std::string const& name) const;
|
getImpl_internal(std::string const& name) const;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
void registerImpl_internal(std::string const& name);
|
void registerImpl_internal(std::string const& name);
|
||||||
void setDefaultProvider_internal(std::string const& name);
|
void setDefaultProvider_internal(std::string const& name);
|
||||||
|
|
||||||
@ -100,7 +97,7 @@ class QPDFCryptoProvider
|
|||||||
Members(Members const&) = delete;
|
Members(Members const&) = delete;
|
||||||
Members& operator=(Members const&) = delete;
|
Members& operator=(Members const&) = delete;
|
||||||
|
|
||||||
typedef std::function<std::shared_ptr<QPDFCryptoImpl> ()> provider_fn;
|
typedef std::function<std::shared_ptr<QPDFCryptoImpl>()> provider_fn;
|
||||||
std::string default_provider;
|
std::string default_provider;
|
||||||
std::map<std::string, provider_fn> providers;
|
std::map<std::string, provider_fn> providers;
|
||||||
};
|
};
|
||||||
|
@ -49,12 +49,14 @@ class QPDFDocumentHelper
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF& getQPDF()
|
QPDF&
|
||||||
|
getQPDF()
|
||||||
{
|
{
|
||||||
return this->qpdf;
|
return this->qpdf;
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF const& getQPDF() const
|
QPDF const&
|
||||||
|
getQPDF() const
|
||||||
{
|
{
|
||||||
return this->qpdf;
|
return this->qpdf;
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
#include <qpdf/QPDFDocumentHelper.hh>
|
#include <qpdf/QPDFDocumentHelper.hh>
|
||||||
|
|
||||||
#include <qpdf/QPDF.hh>
|
|
||||||
#include <qpdf/QPDFNameTreeObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFFileSpecObjectHelper.hh>
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
#include <qpdf/QPDF.hh>
|
||||||
|
#include <qpdf/QPDFFileSpecObjectHelper.hh>
|
||||||
|
#include <qpdf/QPDFNameTreeObjectHelper.hh>
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
// This class provides a higher level interface around document-level
|
// This class provides a higher level interface around document-level
|
||||||
// file attachments, also known as embedded files. These are discussed
|
// file attachments, also known as embedded files. These are discussed
|
||||||
@ -48,8 +48,8 @@ class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper
|
|||||||
bool hasEmbeddedFiles() const;
|
bool hasEmbeddedFiles() const;
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::map<std::string,
|
std::map<std::string, std::shared_ptr<QPDFFileSpecObjectHelper>>
|
||||||
std::shared_ptr<QPDFFileSpecObjectHelper>> getEmbeddedFiles();
|
getEmbeddedFiles();
|
||||||
|
|
||||||
// If an embedded file with the given name exists, return a
|
// If an embedded file with the given name exists, return a
|
||||||
// (shared) pointer to it. Otherwise, return nullptr.
|
// (shared) pointer to it. Otherwise, return nullptr.
|
||||||
|
@ -22,22 +22,23 @@
|
|||||||
#ifndef QPDFEXC_HH
|
#ifndef QPDFEXC_HH
|
||||||
#define QPDFEXC_HH
|
#define QPDFEXC_HH
|
||||||
|
|
||||||
|
#include <qpdf/Constants.h>
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
#include <qpdf/Constants.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
|
class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFExc(qpdf_error_code_e error_code,
|
QPDFExc(
|
||||||
std::string const& filename,
|
qpdf_error_code_e error_code,
|
||||||
std::string const& object,
|
std::string const& filename,
|
||||||
qpdf_offset_t offset,
|
std::string const& object,
|
||||||
std::string const& message);
|
qpdf_offset_t offset,
|
||||||
|
std::string const& message);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~QPDFExc() noexcept
|
virtual ~QPDFExc() noexcept
|
||||||
{
|
{
|
||||||
@ -65,10 +66,11 @@ class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
|
|||||||
std::string const& getMessageDetail() const;
|
std::string const& getMessageDetail() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string createWhat(std::string const& filename,
|
static std::string createWhat(
|
||||||
std::string const& object,
|
std::string const& filename,
|
||||||
qpdf_offset_t offset,
|
std::string const& object,
|
||||||
std::string const& message);
|
qpdf_offset_t offset,
|
||||||
|
std::string const& message);
|
||||||
|
|
||||||
// This class does not use the Members pattern to avoid needless
|
// This class does not use the Members pattern to avoid needless
|
||||||
// memory allocations during exception handling.
|
// memory allocations during exception handling.
|
||||||
|
@ -26,8 +26,8 @@
|
|||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/QPDFEFStreamObjectHelper.hh>
|
#include <qpdf/QPDFEFStreamObjectHelper.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
|
|
||||||
// This class provides a higher level interface around File
|
// This class provides a higher level interface around File
|
||||||
// Specification dictionaries, which are discussed in section 7.11 of
|
// Specification dictionaries, which are discussed in section 7.11 of
|
||||||
@ -77,22 +77,16 @@ class QPDFFileSpecObjectHelper: public QPDFObjectHelper
|
|||||||
// filename, and attach the contents of the specified file as data
|
// filename, and attach the contents of the specified file as data
|
||||||
// in an embedded file stream.
|
// in an embedded file stream.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static
|
static QPDFFileSpecObjectHelper createFileSpec(
|
||||||
QPDFFileSpecObjectHelper createFileSpec(
|
QPDF& qpdf, std::string const& filename, std::string const& fullpath);
|
||||||
QPDF& qpdf,
|
|
||||||
std::string const& filename,
|
|
||||||
std::string const& fullpath);
|
|
||||||
|
|
||||||
// Create a new filespec as an indirect object with the given
|
// Create a new filespec as an indirect object with the given
|
||||||
// unicode filename and embedded file stream. The file name will
|
// unicode filename and embedded file stream. The file name will
|
||||||
// be used as both /UF and /F. If you need to override, call
|
// be used as both /UF and /F. If you need to override, call
|
||||||
// setFilename.
|
// setFilename.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static
|
static QPDFFileSpecObjectHelper createFileSpec(
|
||||||
QPDFFileSpecObjectHelper createFileSpec(
|
QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper);
|
||||||
QPDF& qpdf,
|
|
||||||
std::string const& filename,
|
|
||||||
QPDFEFStreamObjectHelper);
|
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFFileSpecObjectHelper& setDescription(std::string const&);
|
QPDFFileSpecObjectHelper& setDescription(std::string const&);
|
||||||
@ -103,8 +97,7 @@ class QPDFFileSpecObjectHelper: public QPDFObjectHelper
|
|||||||
// might happen to have.
|
// might happen to have.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFFileSpecObjectHelper& setFilename(
|
QPDFFileSpecObjectHelper& setFilename(
|
||||||
std::string const& unicode_name,
|
std::string const& unicode_name, std::string const& compat_name = "");
|
||||||
std::string const& compat_name = "");
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Members
|
class Members
|
||||||
|
@ -185,8 +185,8 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
|||||||
// of a field, use QPDFAcroFormDocumentHelper::setFormFieldName
|
// of a field, use QPDFAcroFormDocumentHelper::setFormFieldName
|
||||||
// instead.
|
// instead.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setFieldAttribute(std::string const& key,
|
void
|
||||||
std::string const& utf8_value);
|
setFieldAttribute(std::string const& key, std::string const& utf8_value);
|
||||||
|
|
||||||
// Set /V (field value) to the given value. If need_appearances is
|
// Set /V (field value) to the given value. If need_appearances is
|
||||||
// true and the field type is either /Tx (text) or /Ch (choice),
|
// true and the field type is either /Tx (text) or /Ch (choice),
|
||||||
|
@ -22,22 +22,21 @@
|
|||||||
#ifndef QPDFJOB_HH
|
#ifndef QPDFJOB_HH
|
||||||
#define QPDFJOB_HH
|
#define QPDFJOB_HH
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
|
||||||
#include <qpdf/Constants.h>
|
#include <qpdf/Constants.h>
|
||||||
|
#include <qpdf/DLL.h>
|
||||||
|
#include <qpdf/PDFVersion.hh>
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/PDFVersion.hh>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include <iostream>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class QPDFWriter;
|
class QPDFWriter;
|
||||||
|
|
||||||
@ -79,8 +78,8 @@ class QPDFJob
|
|||||||
// about converting arguments to UTF-8. This method will mutate
|
// about converting arguments to UTF-8. This method will mutate
|
||||||
// arguments that are passed to it.
|
// arguments that are passed to it.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void initializeFromArgv(char const* const argv[],
|
void initializeFromArgv(
|
||||||
char const* progname_env = nullptr);
|
char const* const argv[], char const* progname_env = nullptr);
|
||||||
|
|
||||||
// Initialize a QPDFJob from json. Passing partial = true prevents
|
// Initialize a QPDFJob from json. Passing partial = true prevents
|
||||||
// this method from doing the final checks (calling
|
// this method from doing the final checks (calling
|
||||||
@ -155,9 +154,10 @@ class QPDFJob
|
|||||||
|
|
||||||
struct PageSpec
|
struct PageSpec
|
||||||
{
|
{
|
||||||
PageSpec(std::string const& filename,
|
PageSpec(
|
||||||
char const* password,
|
std::string const& filename,
|
||||||
std::string const& range);
|
char const* password,
|
||||||
|
std::string const& range);
|
||||||
|
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::shared_ptr<char> password;
|
std::shared_ptr<char> password;
|
||||||
@ -203,13 +203,14 @@ class QPDFJob
|
|||||||
{
|
{
|
||||||
friend class QPDFJob;
|
friend class QPDFJob;
|
||||||
friend class Config;
|
friend class Config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Config* endAddAttachment();
|
Config* endAddAttachment();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
AttConfig* file(std::string const& parameter);
|
AttConfig* file(std::string const& parameter);
|
||||||
|
|
||||||
# include <qpdf/auto_job_c_att.hh>
|
#include <qpdf/auto_job_c_att.hh>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AttConfig(Config*);
|
AttConfig(Config*);
|
||||||
@ -223,13 +224,14 @@ class QPDFJob
|
|||||||
{
|
{
|
||||||
friend class QPDFJob;
|
friend class QPDFJob;
|
||||||
friend class Config;
|
friend class Config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Config* endCopyAttachmentsFrom();
|
Config* endCopyAttachmentsFrom();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
CopyAttConfig* file(std::string const& parameter);
|
CopyAttConfig* file(std::string const& parameter);
|
||||||
|
|
||||||
# include <qpdf/auto_job_c_copy_att.hh>
|
#include <qpdf/auto_job_c_copy_att.hh>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CopyAttConfig(Config*);
|
CopyAttConfig(Config*);
|
||||||
@ -243,15 +245,17 @@ class QPDFJob
|
|||||||
{
|
{
|
||||||
friend class QPDFJob;
|
friend class QPDFJob;
|
||||||
friend class Config;
|
friend class Config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Config* endPages();
|
Config* endPages();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
PagesConfig* pageSpec(std::string const& filename,
|
PagesConfig* pageSpec(
|
||||||
std::string const& range,
|
std::string const& filename,
|
||||||
char const* password = nullptr);
|
std::string const& range,
|
||||||
|
char const* password = nullptr);
|
||||||
|
|
||||||
# include <qpdf/auto_job_c_pages.hh>
|
#include <qpdf/auto_job_c_pages.hh>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PagesConfig(Config*);
|
PagesConfig(Config*);
|
||||||
@ -264,13 +268,14 @@ class QPDFJob
|
|||||||
{
|
{
|
||||||
friend class QPDFJob;
|
friend class QPDFJob;
|
||||||
friend class Config;
|
friend class Config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Config* endUnderlayOverlay();
|
Config* endUnderlayOverlay();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
UOConfig* file(std::string const& parameter);
|
UOConfig* file(std::string const& parameter);
|
||||||
|
|
||||||
# include <qpdf/auto_job_c_uo.hh>
|
#include <qpdf/auto_job_c_uo.hh>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UOConfig(Config*);
|
UOConfig(Config*);
|
||||||
@ -283,13 +288,14 @@ class QPDFJob
|
|||||||
{
|
{
|
||||||
friend class QPDFJob;
|
friend class QPDFJob;
|
||||||
friend class Config;
|
friend class Config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Config* endEncrypt();
|
Config* endEncrypt();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
EncConfig* file(std::string const& parameter);
|
EncConfig* file(std::string const& parameter);
|
||||||
|
|
||||||
# include <qpdf/auto_job_c_enc.hh>
|
#include <qpdf/auto_job_c_enc.hh>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncConfig(Config*);
|
EncConfig(Config*);
|
||||||
@ -301,6 +307,7 @@ class QPDFJob
|
|||||||
class Config
|
class Config
|
||||||
{
|
{
|
||||||
friend class QPDFJob;
|
friend class QPDFJob;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Proxy to QPDFJob::checkConfiguration()
|
// Proxy to QPDFJob::checkConfiguration()
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -331,7 +338,7 @@ class QPDFJob
|
|||||||
std::string const& user_password,
|
std::string const& user_password,
|
||||||
std::string const& owner_password);
|
std::string const& owner_password);
|
||||||
|
|
||||||
# include <qpdf/auto_job_c_main.hh>
|
#include <qpdf/auto_job_c_main.hh>
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Config() = delete;
|
Config() = delete;
|
||||||
@ -444,32 +451,37 @@ class QPDFJob
|
|||||||
|
|
||||||
// Basic file processing
|
// Basic file processing
|
||||||
std::shared_ptr<QPDF> processFile(
|
std::shared_ptr<QPDF> processFile(
|
||||||
char const* filename, char const* password,
|
char const* filename, char const* password, bool used_for_input);
|
||||||
bool used_for_input);
|
|
||||||
std::shared_ptr<QPDF> processInputSource(
|
std::shared_ptr<QPDF> processInputSource(
|
||||||
PointerHolder<InputSource> is, char const* password,
|
PointerHolder<InputSource> is,
|
||||||
|
char const* password,
|
||||||
bool used_for_input);
|
bool used_for_input);
|
||||||
std::shared_ptr<QPDF> doProcess(
|
std::shared_ptr<QPDF> doProcess(
|
||||||
std::function<void(QPDF*, char const*)> fn,
|
std::function<void(QPDF*, char const*)> fn,
|
||||||
char const* password, bool empty, bool used_for_input);
|
char const* password,
|
||||||
|
bool empty,
|
||||||
|
bool used_for_input);
|
||||||
std::shared_ptr<QPDF> doProcessOnce(
|
std::shared_ptr<QPDF> doProcessOnce(
|
||||||
std::function<void(QPDF*, char const*)> fn,
|
std::function<void(QPDF*, char const*)> fn,
|
||||||
char const* password, bool empty, bool used_for_input);
|
char const* password,
|
||||||
|
bool empty,
|
||||||
|
bool used_for_input);
|
||||||
|
|
||||||
// Transformations
|
// Transformations
|
||||||
void setQPDFOptions(QPDF& pdf);
|
void setQPDFOptions(QPDF& pdf);
|
||||||
void handlePageSpecs(
|
void handlePageSpecs(
|
||||||
QPDF& pdf, bool& warnings,
|
QPDF& pdf,
|
||||||
|
bool& warnings,
|
||||||
std::vector<std::shared_ptr<QPDF>>& page_heap);
|
std::vector<std::shared_ptr<QPDF>>& page_heap);
|
||||||
bool shouldRemoveUnreferencedResources(QPDF& pdf);
|
bool shouldRemoveUnreferencedResources(QPDF& pdf);
|
||||||
void handleRotations(QPDF& pdf);
|
void handleRotations(QPDF& pdf);
|
||||||
void getUOPagenos(UnderOverlay& uo,
|
void
|
||||||
std::map<int, std::vector<int> >& pagenos);
|
getUOPagenos(UnderOverlay& uo, std::map<int, std::vector<int>>& pagenos);
|
||||||
void handleUnderOverlay(QPDF& pdf);
|
void handleUnderOverlay(QPDF& pdf);
|
||||||
void doUnderOverlayForPage(
|
void doUnderOverlayForPage(
|
||||||
QPDF& pdf,
|
QPDF& pdf,
|
||||||
UnderOverlay& uo,
|
UnderOverlay& uo,
|
||||||
std::map<int, std::vector<int> >& pagenos,
|
std::map<int, std::vector<int>>& pagenos,
|
||||||
size_t page_idx,
|
size_t page_idx,
|
||||||
std::map<int, QPDFObjectHandle>& fo,
|
std::map<int, QPDFObjectHandle>& fo,
|
||||||
std::vector<QPDFPageObjectHelper>& pages,
|
std::vector<QPDFPageObjectHelper>& pages,
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#ifndef QPDFMATRIX_HH
|
#ifndef QPDFMATRIX_HH
|
||||||
#define QPDFMATRIX_HH
|
#define QPDFMATRIX_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// This class represents a PDF transformation matrix using a tuple
|
// This class represents a PDF transformation matrix using a tuple
|
||||||
@ -41,8 +41,7 @@ class QPDFMatrix
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFMatrix();
|
QPDFMatrix();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFMatrix(double a, double b, double c,
|
QPDFMatrix(double a, double b, double c, double d, double e, double f);
|
||||||
double d, double e, double f);
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFMatrix(QPDFObjectHandle::Matrix const&);
|
QPDFMatrix(QPDFObjectHandle::Matrix const&);
|
||||||
|
|
||||||
@ -83,21 +82,22 @@ class QPDFMatrix
|
|||||||
// bounds the polygon resulting from transforming the four
|
// bounds the polygon resulting from transforming the four
|
||||||
// corners.
|
// corners.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle::Rectangle transformRectangle(
|
QPDFObjectHandle::Rectangle
|
||||||
QPDFObjectHandle::Rectangle r) const;
|
transformRectangle(QPDFObjectHandle::Rectangle r) const;
|
||||||
// ABI: delete non-const version
|
// ABI: delete non-const version
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle::Rectangle transformRectangle(
|
QPDFObjectHandle::Rectangle
|
||||||
QPDFObjectHandle::Rectangle r);
|
transformRectangle(QPDFObjectHandle::Rectangle r);
|
||||||
|
|
||||||
// operator== tests for exact equality, not considering deltas for
|
// operator== tests for exact equality, not considering deltas for
|
||||||
// floating point.
|
// floating point.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator==(QPDFMatrix const& rhs) const;
|
bool operator==(QPDFMatrix const& rhs) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(QPDFMatrix const& rhs) const
|
bool
|
||||||
|
operator!=(QPDFMatrix const& rhs) const
|
||||||
{
|
{
|
||||||
return ! operator==(rhs);
|
return !operator==(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
double a;
|
double a;
|
||||||
|
@ -22,11 +22,11 @@
|
|||||||
#ifndef QPDFNAMETREEOBJECTHELPER_HH
|
#ifndef QPDFNAMETREEOBJECTHELPER_HH
|
||||||
#define QPDFNAMETREEOBJECTHELPER_HH
|
#define QPDFNAMETREEOBJECTHELPER_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFObjGen.hh>
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
|
#include <qpdf/QPDFObjectHelper.hh>
|
||||||
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
@ -48,16 +48,14 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
// The qpdf object is required so that this class can issue
|
// The qpdf object is required so that this class can issue
|
||||||
// warnings, attempt repairs, and add indirect objects.
|
// warnings, attempt repairs, and add indirect objects.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&,
|
QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true);
|
||||||
bool auto_repair = true);
|
|
||||||
|
|
||||||
// ABI: Legacy Constructor will be removed in QPDF 11. A
|
// ABI: Legacy Constructor will be removed in QPDF 11. A
|
||||||
// QPDFNameTreeObjectHelper constructed in this way can't be
|
// QPDFNameTreeObjectHelper constructed in this way can't be
|
||||||
// modified or repaired and will silently ignore problems in the
|
// modified or repaired and will silently ignore problems in the
|
||||||
// structure.
|
// structure.
|
||||||
[[deprecated("use constructor that takes QPDF&")]]
|
[[deprecated("use constructor that takes QPDF&")]] QPDF_DLL
|
||||||
QPDF_DLL
|
QPDFNameTreeObjectHelper(QPDFObjectHandle);
|
||||||
QPDFNameTreeObjectHelper(QPDFObjectHandle);
|
|
||||||
|
|
||||||
// Create an empty name tree
|
// Create an empty name tree
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -80,6 +78,7 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
class iterator
|
class iterator
|
||||||
{
|
{
|
||||||
friend class QPDFNameTreeObjectHelper;
|
friend class QPDFNameTreeObjectHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<std::string, QPDFObjectHandle> T;
|
typedef std::pair<std::string, QPDFObjectHandle> T;
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
@ -94,7 +93,8 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator++();
|
iterator& operator++();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator++(int)
|
iterator
|
||||||
|
operator++(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@ -103,7 +103,8 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator--();
|
iterator& operator--();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator--(int)
|
iterator
|
||||||
|
operator--(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@ -116,9 +117,10 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator==(iterator const& other) const;
|
bool operator==(iterator const& other) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(iterator const& other) const
|
bool
|
||||||
|
operator!=(iterator const& other) const
|
||||||
{
|
{
|
||||||
return ! operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DANGER: this method can create inconsistent trees if not
|
// DANGER: this method can create inconsistent trees if not
|
||||||
@ -162,8 +164,8 @@ class QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
|||||||
// Find the entry with the given key. If return_prev_if_not_found
|
// Find the entry with the given key. If return_prev_if_not_found
|
||||||
// is true and the item is not found, return the next lower item.
|
// is true and the item is not found, return the next lower item.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator find(std::string const& key,
|
iterator
|
||||||
bool return_prev_if_not_found = false);
|
find(std::string const& key, bool return_prev_if_not_found = false);
|
||||||
|
|
||||||
// Insert a new item. If the key already exists, it is replaced.
|
// Insert a new item. If the key already exists, it is replaced.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#ifndef QPDFNUMBERTREEOBJECTHELPER_HH
|
#ifndef QPDFNUMBERTREEOBJECTHELPER_HH
|
||||||
#define QPDFNUMBERTREEOBJECTHELPER_HH
|
#define QPDFNUMBERTREEOBJECTHELPER_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFObjGen.hh>
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
|
#include <qpdf/QPDFObjectHelper.hh>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -45,16 +45,15 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
// The qpdf object is required so that this class can issue
|
// The qpdf object is required so that this class can issue
|
||||||
// warnings, attempt repairs, and add indirect objects.
|
// warnings, attempt repairs, and add indirect objects.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&,
|
QPDFNumberTreeObjectHelper(
|
||||||
bool auto_repair = true);
|
QPDFObjectHandle, QPDF&, bool auto_repair = true);
|
||||||
|
|
||||||
// ABI: Legacy Constructor will be removed in QPDF 11. A
|
// ABI: Legacy Constructor will be removed in QPDF 11. A
|
||||||
// QPDFNumberTreeObjectHelper constructed in this way can't be
|
// QPDFNumberTreeObjectHelper constructed in this way can't be
|
||||||
// modified or repaired and will silently ignore problems in the
|
// modified or repaired and will silently ignore problems in the
|
||||||
// structure.
|
// structure.
|
||||||
[[deprecated("use constructor that takes QPDF&")]]
|
[[deprecated("use constructor that takes QPDF&")]] QPDF_DLL
|
||||||
QPDF_DLL
|
QPDFNumberTreeObjectHelper(QPDFObjectHandle);
|
||||||
QPDFNumberTreeObjectHelper(QPDFObjectHandle);
|
|
||||||
|
|
||||||
// ABI: = default
|
// ABI: = default
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -93,12 +92,13 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
// oh to the value with index 3, and set offset to 2 (5 - 3). See
|
// oh to the value with index 3, and set offset to 2 (5 - 3). See
|
||||||
// also find().
|
// also find().
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh,
|
bool findObjectAtOrBelow(
|
||||||
numtree_number& offset);
|
numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset);
|
||||||
|
|
||||||
class iterator
|
class iterator
|
||||||
{
|
{
|
||||||
friend class QPDFNumberTreeObjectHelper;
|
friend class QPDFNumberTreeObjectHelper;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<numtree_number, QPDFObjectHandle> T;
|
typedef std::pair<numtree_number, QPDFObjectHandle> T;
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
@ -113,7 +113,8 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator++();
|
iterator& operator++();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator++(int)
|
iterator
|
||||||
|
operator++(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@ -122,7 +123,8 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator--();
|
iterator& operator--();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator--(int)
|
iterator
|
||||||
|
operator--(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@ -135,9 +137,10 @@ class QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator==(iterator const& other) const;
|
bool operator==(iterator const& other) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(iterator const& other) const
|
bool
|
||||||
|
operator!=(iterator const& other) const
|
||||||
{
|
{
|
||||||
return ! operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DANGER: this method can create inconsistent trees if not
|
// DANGER: this method can create inconsistent trees if not
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
#ifndef QPDFOBJECT_HH
|
#ifndef QPDFOBJECT_HH
|
||||||
#define QPDFOBJECT_HH
|
#define QPDFOBJECT_HH
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
|
||||||
#include <qpdf/Types.h>
|
|
||||||
#include <qpdf/JSON.hh>
|
|
||||||
#include <qpdf/Constants.h>
|
#include <qpdf/Constants.h>
|
||||||
|
#include <qpdf/DLL.h>
|
||||||
|
#include <qpdf/JSON.hh>
|
||||||
|
#include <qpdf/Types.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -62,7 +62,9 @@ class QPDF_DLL_CLASS QPDFObject
|
|||||||
static constexpr object_type_e ot_operator = ::ot_operator;
|
static constexpr object_type_e ot_operator = ::ot_operator;
|
||||||
static constexpr object_type_e ot_inlineimage = ::ot_inlineimage;
|
static constexpr object_type_e ot_inlineimage = ::ot_inlineimage;
|
||||||
|
|
||||||
virtual ~QPDFObject() {}
|
virtual ~QPDFObject()
|
||||||
|
{
|
||||||
|
}
|
||||||
virtual std::string unparse() = 0;
|
virtual std::string unparse() = 0;
|
||||||
virtual JSON getJSON() = 0;
|
virtual JSON getJSON() = 0;
|
||||||
|
|
||||||
@ -78,11 +80,12 @@ class QPDF_DLL_CLASS QPDFObject
|
|||||||
{
|
{
|
||||||
friend class QPDF;
|
friend class QPDF;
|
||||||
friend class QPDFObjectHandle;
|
friend class QPDFObjectHandle;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void releaseResolved(QPDFObject* o)
|
static void
|
||||||
|
releaseResolved(QPDFObject* o)
|
||||||
{
|
{
|
||||||
if (o)
|
if (o) {
|
||||||
{
|
|
||||||
o->releaseResolved();
|
o->releaseResolved();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,7 +100,10 @@ class QPDF_DLL_CLASS QPDFObject
|
|||||||
qpdf_offset_t getParsedOffset();
|
qpdf_offset_t getParsedOffset();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void releaseResolved() {}
|
virtual void
|
||||||
|
releaseResolved()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDFObject(QPDFObject const&) = delete;
|
QPDFObject(QPDFObject const&) = delete;
|
||||||
|
@ -22,21 +22,21 @@
|
|||||||
#ifndef QPDFOBJECTHANDLE_HH
|
#ifndef QPDFOBJECTHANDLE_HH
|
||||||
#define QPDFOBJECTHANDLE_HH
|
#define QPDFOBJECTHANDLE_HH
|
||||||
|
|
||||||
|
#include <qpdf/Constants.h>
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
#include <qpdf/Constants.h>
|
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
|
||||||
#include <map>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <qpdf/QPDFObjGen.hh>
|
|
||||||
#include <qpdf/PointerHolder.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
#include <qpdf/Buffer.hh>
|
||||||
#include <qpdf/InputSource.hh>
|
#include <qpdf/InputSource.hh>
|
||||||
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
#include <qpdf/QPDFTokenizer.hh>
|
#include <qpdf/QPDFTokenizer.hh>
|
||||||
|
|
||||||
#include <qpdf/QPDFObject.hh>
|
#include <qpdf/QPDFObject.hh>
|
||||||
@ -117,12 +117,15 @@ class QPDFObjectHandle
|
|||||||
// version of the method, which should also return a boolean
|
// version of the method, which should also return a boolean
|
||||||
// indicating whether it ran without errors.
|
// indicating whether it ran without errors.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void provideStreamData(int objid, int generation,
|
virtual void
|
||||||
Pipeline* pipeline);
|
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual bool provideStreamData(
|
virtual bool provideStreamData(
|
||||||
int objid, int generation, Pipeline* pipeline,
|
int objid,
|
||||||
bool suppress_warnings, bool will_retry);
|
int generation,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
bool suppress_warnings,
|
||||||
|
bool will_retry);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool supportsRetry();
|
bool supportsRetry();
|
||||||
|
|
||||||
@ -183,8 +186,10 @@ class QPDFObjectHandle
|
|||||||
class PipelineAccessor
|
class PipelineAccessor
|
||||||
{
|
{
|
||||||
friend class Pl_QPDFTokenizer;
|
friend class Pl_QPDFTokenizer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void setPipeline(TokenFilter* f, Pipeline* p)
|
static void
|
||||||
|
setPipeline(TokenFilter* f, Pipeline* p)
|
||||||
{
|
{
|
||||||
f->setPipeline(p);
|
f->setPipeline(p);
|
||||||
}
|
}
|
||||||
@ -230,8 +235,8 @@ class QPDFObjectHandle
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void handleObject(QPDFObjectHandle);
|
virtual void handleObject(QPDFObjectHandle);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void handleObject(
|
virtual void
|
||||||
QPDFObjectHandle, size_t offset, size_t length);
|
handleObject(QPDFObjectHandle, size_t offset, size_t length);
|
||||||
|
|
||||||
virtual void handleEOF() = 0;
|
virtual void handleEOF() = 0;
|
||||||
|
|
||||||
@ -261,8 +266,7 @@ class QPDFObjectHandle
|
|||||||
ury(0.0)
|
ury(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Rectangle(double llx, double lly,
|
Rectangle(double llx, double lly, double urx, double ury) :
|
||||||
double urx, double ury) :
|
|
||||||
llx(llx),
|
llx(llx),
|
||||||
lly(lly),
|
lly(lly),
|
||||||
urx(urx),
|
urx(urx),
|
||||||
@ -292,8 +296,7 @@ class QPDFObjectHandle
|
|||||||
f(0.0)
|
f(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Matrix(double a, double b, double c,
|
Matrix(double a, double b, double c, double d, double e, double f) :
|
||||||
double d, double e, double f) :
|
|
||||||
a(a),
|
a(a),
|
||||||
b(b),
|
b(b),
|
||||||
c(c),
|
c(c),
|
||||||
@ -316,8 +319,7 @@ class QPDFObjectHandle
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle(QPDFObjectHandle const&) = default;
|
QPDFObjectHandle(QPDFObjectHandle const&) = default;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle&
|
QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
|
||||||
operator=(QPDFObjectHandle const&) = default;
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool isInitialized() const;
|
bool isInitialized() const;
|
||||||
|
|
||||||
@ -381,14 +383,14 @@ class QPDFObjectHandle
|
|||||||
// True if the object is a dictionary of the specified type and
|
// True if the object is a dictionary of the specified type and
|
||||||
// subtype, if any.
|
// subtype, if any.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool isDictionaryOfType(std::string const& type,
|
bool isDictionaryOfType(
|
||||||
std::string const& subtype = "");
|
std::string const& type, std::string const& subtype = "");
|
||||||
|
|
||||||
// True if the object is a stream of the specified type and
|
// True if the object is a stream of the specified type and
|
||||||
// subtype, if any.
|
// subtype, if any.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool isStreamOfType(std::string const& type,
|
bool
|
||||||
std::string const& subtype = "");
|
isStreamOfType(std::string const& type, std::string const& subtype = "");
|
||||||
|
|
||||||
// Public factory methods
|
// Public factory methods
|
||||||
|
|
||||||
@ -406,8 +408,9 @@ class QPDFObjectHandle
|
|||||||
// in the message of any QPDFExc exception thrown for invalid
|
// in the message of any QPDFExc exception thrown for invalid
|
||||||
// syntax. See also the global `operator ""_qpdf` defined below.
|
// syntax. See also the global `operator ""_qpdf` defined below.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle parse(std::string const& object_str,
|
static QPDFObjectHandle parse(
|
||||||
std::string const& object_description = "");
|
std::string const& object_str,
|
||||||
|
std::string const& object_description = "");
|
||||||
|
|
||||||
// Construct an object of any type from a string representation of
|
// Construct an object of any type from a string representation of
|
||||||
// the object. Indirect object syntax (obj gen R) is allowed and
|
// the object. Indirect object syntax (obj gen R) is allowed and
|
||||||
@ -419,9 +422,10 @@ class QPDFObjectHandle
|
|||||||
// object, which will just be the first number and will report
|
// object, which will just be the first number and will report
|
||||||
// that there is trailing data at the end of the string.
|
// that there is trailing data at the end of the string.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle parse(QPDF* context,
|
static QPDFObjectHandle parse(
|
||||||
std::string const& object_str,
|
QPDF* context,
|
||||||
std::string const& object_description = "");
|
std::string const& object_str,
|
||||||
|
std::string const& object_description = "");
|
||||||
|
|
||||||
// Construct an object as above by reading from the given
|
// Construct an object as above by reading from the given
|
||||||
// InputSource at its current position and using the tokenizer you
|
// InputSource at its current position and using the tokenizer you
|
||||||
@ -429,11 +433,13 @@ class QPDFObjectHandle
|
|||||||
// This method is intended to be called by QPDF for parsing
|
// This method is intended to be called by QPDF for parsing
|
||||||
// objects that are ready from the object's input stream.
|
// objects that are ready from the object's input stream.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle parse(PointerHolder<InputSource> input,
|
static QPDFObjectHandle parse(
|
||||||
std::string const& object_description,
|
PointerHolder<InputSource> input,
|
||||||
QPDFTokenizer&, bool& empty,
|
std::string const& object_description,
|
||||||
StringDecrypter* decrypter,
|
QPDFTokenizer&,
|
||||||
QPDF* context);
|
bool& empty,
|
||||||
|
StringDecrypter* decrypter,
|
||||||
|
QPDF* context);
|
||||||
|
|
||||||
// Return the offset where the object was found when parsed. A
|
// Return the offset where the object was found when parsed. A
|
||||||
// negative value means that the object was created without
|
// negative value means that the object was created without
|
||||||
@ -449,8 +455,8 @@ class QPDFObjectHandle
|
|||||||
// error messages will also be more useful because the page object
|
// error messages will also be more useful because the page object
|
||||||
// information will be known.
|
// information will be known.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static void parseContentStream(QPDFObjectHandle stream_or_array,
|
static void parseContentStream(
|
||||||
ParserCallbacks* callbacks);
|
QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks);
|
||||||
|
|
||||||
// When called on a stream or stream array that is some page's
|
// When called on a stream or stream array that is some page's
|
||||||
// content streams, do the same as pipePageContents. This method
|
// content streams, do the same as pipePageContents. This method
|
||||||
@ -469,8 +475,10 @@ class QPDFObjectHandle
|
|||||||
// Pl_Concatenate and then call manualFinish() on the
|
// Pl_Concatenate and then call manualFinish() on the
|
||||||
// Pl_Concatenate pipeline at the end.
|
// Pl_Concatenate pipeline at the end.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void pipeContentStreams(Pipeline* p, std::string const& description,
|
void pipeContentStreams(
|
||||||
std::string& all_description);
|
Pipeline* p,
|
||||||
|
std::string const& description,
|
||||||
|
std::string& all_description);
|
||||||
|
|
||||||
// As of qpdf 8, it is possible to add custom token filters to a
|
// As of qpdf 8, it is possible to add custom token filters to a
|
||||||
// stream. The tokenized stream data is passed through the token
|
// stream. The tokenized stream data is passed through the token
|
||||||
@ -525,8 +533,8 @@ class QPDFObjectHandle
|
|||||||
// ABI: combine with other newReal by adding trim_trailing_zeroes
|
// ABI: combine with other newReal by adding trim_trailing_zeroes
|
||||||
// above as an optional parameter with a default of true.
|
// above as an optional parameter with a default of true.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle newReal(double value, int decimal_places,
|
static QPDFObjectHandle
|
||||||
bool trim_trailing_zeroes);
|
newReal(double value, int decimal_places, bool trim_trailing_zeroes);
|
||||||
// Note about name objects: qpdf's internal representation of a
|
// Note about name objects: qpdf's internal representation of a
|
||||||
// PDF name is a sequence of bytes, excluding the NUL character,
|
// PDF name is a sequence of bytes, excluding the NUL character,
|
||||||
// and starting with a slash. Name objects as represented in the
|
// and starting with a slash. Name objects as represented in the
|
||||||
@ -562,8 +570,8 @@ class QPDFObjectHandle
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle newArray();
|
static QPDFObjectHandle newArray();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle newArray(
|
static QPDFObjectHandle
|
||||||
std::vector<QPDFObjectHandle> const& items);
|
newArray(std::vector<QPDFObjectHandle> const& items);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle newArray(Rectangle const&);
|
static QPDFObjectHandle newArray(Rectangle const&);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -573,8 +581,8 @@ class QPDFObjectHandle
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle newDictionary();
|
static QPDFObjectHandle newDictionary();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
static QPDFObjectHandle newDictionary(
|
static QPDFObjectHandle
|
||||||
std::map<std::string, QPDFObjectHandle> const& items);
|
newDictionary(std::map<std::string, QPDFObjectHandle> const& items);
|
||||||
|
|
||||||
// Create an array from a rectangle. Equivalent to the rectangle
|
// Create an array from a rectangle. Equivalent to the rectangle
|
||||||
// form of newArray.
|
// form of newArray.
|
||||||
@ -646,8 +654,8 @@ class QPDFObjectHandle
|
|||||||
// with proper context in some cases where it would otherwise
|
// with proper context in some cases where it would otherwise
|
||||||
// raise exceptions.
|
// raise exceptions.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setObjectDescription(QPDF* owning_qpdf,
|
void setObjectDescription(
|
||||||
std::string const& object_description);
|
QPDF* owning_qpdf, std::string const& object_description);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool hasObjectDescription();
|
bool hasObjectDescription();
|
||||||
|
|
||||||
@ -959,8 +967,8 @@ class QPDFObjectHandle
|
|||||||
// ABI: remove this version and make resource_names default to
|
// ABI: remove this version and make resource_names default to
|
||||||
// nullptr.
|
// nullptr.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string getUniqueResourceName(std::string const& prefix,
|
std::string
|
||||||
int& min_suffix);
|
getUniqueResourceName(std::string const& prefix, int& min_suffix);
|
||||||
|
|
||||||
// Return the QPDF object that owns an indirect object. Returns
|
// Return the QPDF object that owns an indirect object. Returns
|
||||||
// null for a direct object.
|
// null for a direct object.
|
||||||
@ -1081,8 +1089,8 @@ class QPDFObjectHandle
|
|||||||
// Returns filtered (uncompressed) stream data. Throws an
|
// Returns filtered (uncompressed) stream data. Throws an
|
||||||
// exception if the stream is filtered and we can't decode it.
|
// exception if the stream is filtered and we can't decode it.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
PointerHolder<Buffer> getStreamData(
|
PointerHolder<Buffer>
|
||||||
qpdf_stream_decode_level_e level = qpdf_dl_generalized);
|
getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized);
|
||||||
|
|
||||||
// Returns unfiltered (raw) stream data.
|
// Returns unfiltered (raw) stream data.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -1146,21 +1154,24 @@ class QPDFObjectHandle
|
|||||||
// Return value is overall success, even if filtering is not
|
// Return value is overall success, even if filtering is not
|
||||||
// requested.
|
// requested.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool pipeStreamData(Pipeline*, bool* filtering_attempted,
|
bool pipeStreamData(
|
||||||
int encode_flags,
|
Pipeline*,
|
||||||
qpdf_stream_decode_level_e decode_level,
|
bool* filtering_attempted,
|
||||||
bool suppress_warnings = false,
|
int encode_flags,
|
||||||
bool will_retry = false);
|
qpdf_stream_decode_level_e decode_level,
|
||||||
|
bool suppress_warnings = false,
|
||||||
|
bool will_retry = false);
|
||||||
|
|
||||||
// Legacy version. Return value is whether filtering was
|
// Legacy version. Return value is whether filtering was
|
||||||
// attempted. There is no way to determine success if filtering
|
// attempted. There is no way to determine success if filtering
|
||||||
// was not attempted.
|
// was not attempted.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool pipeStreamData(Pipeline*,
|
bool pipeStreamData(
|
||||||
int encode_flags,
|
Pipeline*,
|
||||||
qpdf_stream_decode_level_e decode_level,
|
int encode_flags,
|
||||||
bool suppress_warnings = false,
|
qpdf_stream_decode_level_e decode_level,
|
||||||
bool will_retry = false);
|
bool suppress_warnings = false,
|
||||||
|
bool will_retry = false);
|
||||||
|
|
||||||
// Legacy pipeStreamData. This maps to the the flags-based
|
// Legacy pipeStreamData. This maps to the the flags-based
|
||||||
// pipeStreamData as follows:
|
// pipeStreamData as follows:
|
||||||
@ -1170,8 +1181,7 @@ class QPDFObjectHandle
|
|||||||
// compress = true -> encode_flags |= qpdf_sf_compress
|
// compress = true -> encode_flags |= qpdf_sf_compress
|
||||||
// Return value is whether filtering was attempted.
|
// Return value is whether filtering was attempted.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool pipeStreamData(Pipeline*, bool filter,
|
bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress);
|
||||||
bool normalize, bool compress);
|
|
||||||
|
|
||||||
// Replace a stream's dictionary. The new dictionary must be
|
// Replace a stream's dictionary. The new dictionary must be
|
||||||
// consistent with the stream's data. This is most appropriately
|
// consistent with the stream's data. This is most appropriately
|
||||||
@ -1190,18 +1200,20 @@ class QPDFObjectHandle
|
|||||||
// interpreted as if the data read from the file, after any
|
// interpreted as if the data read from the file, after any
|
||||||
// decryption filters have been applied, is as presented.
|
// decryption filters have been applied, is as presented.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void replaceStreamData(PointerHolder<Buffer> data,
|
void replaceStreamData(
|
||||||
QPDFObjectHandle const& filter,
|
PointerHolder<Buffer> data,
|
||||||
QPDFObjectHandle const& decode_parms);
|
QPDFObjectHandle const& filter,
|
||||||
|
QPDFObjectHandle const& decode_parms);
|
||||||
|
|
||||||
// Replace the stream's stream data with the given string.
|
// Replace the stream's stream data with the given string.
|
||||||
// This method will create a copy of the data rather than using
|
// This method will create a copy of the data rather than using
|
||||||
// the user-provided buffer as in the PointerHolder<Buffer> version
|
// the user-provided buffer as in the PointerHolder<Buffer> version
|
||||||
// of replaceStreamData.
|
// of replaceStreamData.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void replaceStreamData(std::string const& data,
|
void replaceStreamData(
|
||||||
QPDFObjectHandle const& filter,
|
std::string const& data,
|
||||||
QPDFObjectHandle const& decode_parms);
|
QPDFObjectHandle const& filter,
|
||||||
|
QPDFObjectHandle const& decode_parms);
|
||||||
|
|
||||||
// As above, replace this stream's stream data. Instead of
|
// As above, replace this stream's stream data. Instead of
|
||||||
// directly providing a buffer with the stream data, call the
|
// directly providing a buffer with the stream data, call the
|
||||||
@ -1229,9 +1241,10 @@ class QPDFObjectHandle
|
|||||||
// parameter. You can also simplify your code by not having to
|
// parameter. You can also simplify your code by not having to
|
||||||
// compute the length in advance.
|
// compute the length in advance.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void replaceStreamData(PointerHolder<StreamDataProvider> provider,
|
void replaceStreamData(
|
||||||
QPDFObjectHandle const& filter,
|
PointerHolder<StreamDataProvider> provider,
|
||||||
QPDFObjectHandle const& decode_parms);
|
QPDFObjectHandle const& filter,
|
||||||
|
QPDFObjectHandle const& decode_parms);
|
||||||
|
|
||||||
// Starting in qpdf 10.2, you can use C++-11 function objects
|
// Starting in qpdf 10.2, you can use C++-11 function objects
|
||||||
// instead of StreamDataProvider.
|
// instead of StreamDataProvider.
|
||||||
@ -1240,16 +1253,16 @@ class QPDFObjectHandle
|
|||||||
// a one-liner to replace stream data with the contents of a file,
|
// a one-liner to replace stream data with the contents of a file,
|
||||||
// pass QUtil::file_provider(filename) as provider.
|
// pass QUtil::file_provider(filename) as provider.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void replaceStreamData(std::function<void(Pipeline*)> provider,
|
void replaceStreamData(
|
||||||
QPDFObjectHandle const& filter,
|
std::function<void(Pipeline*)> provider,
|
||||||
QPDFObjectHandle const& decode_parms);
|
QPDFObjectHandle const& filter,
|
||||||
|
QPDFObjectHandle const& decode_parms);
|
||||||
// The provider should write the stream data to the pipeline,
|
// The provider should write the stream data to the pipeline,
|
||||||
// returning true if it succeeded without errors.
|
// returning true if it succeeded without errors.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void replaceStreamData(
|
void replaceStreamData(
|
||||||
std::function<bool(Pipeline*,
|
std::function<bool(Pipeline*, bool suppress_warnings, bool will_retry)>
|
||||||
bool suppress_warnings,
|
provider,
|
||||||
bool will_retry)> provider,
|
|
||||||
QPDFObjectHandle const& filter,
|
QPDFObjectHandle const& filter,
|
||||||
QPDFObjectHandle const& decode_parms);
|
QPDFObjectHandle const& decode_parms);
|
||||||
|
|
||||||
@ -1321,8 +1334,8 @@ class QPDFObjectHandle
|
|||||||
// descriptions. See comments on setObjectDescription for
|
// descriptions. See comments on setObjectDescription for
|
||||||
// additional details.
|
// additional details.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void warnIfPossible(std::string const& warning,
|
void warnIfPossible(
|
||||||
bool throw_if_no_description = false);
|
std::string const& warning, bool throw_if_no_description = false);
|
||||||
|
|
||||||
// Initializers for objects. This Factory class gives the QPDF
|
// Initializers for objects. This Factory class gives the QPDF
|
||||||
// class specific permission to call factory methods without
|
// class specific permission to call factory methods without
|
||||||
@ -1330,16 +1343,22 @@ class QPDFObjectHandle
|
|||||||
class Factory
|
class Factory
|
||||||
{
|
{
|
||||||
friend class QPDF;
|
friend class QPDF;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QPDFObjectHandle newIndirect(QPDF* qpdf,
|
static QPDFObjectHandle
|
||||||
int objid, int generation)
|
newIndirect(QPDF* qpdf, int objid, int generation)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::newIndirect(qpdf, objid, generation);
|
return QPDFObjectHandle::newIndirect(qpdf, objid, generation);
|
||||||
}
|
}
|
||||||
// object must be dictionary object
|
// object must be dictionary object
|
||||||
static QPDFObjectHandle newStream(
|
static QPDFObjectHandle
|
||||||
QPDF* qpdf, int objid, int generation,
|
newStream(
|
||||||
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)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::newStream(
|
return QPDFObjectHandle::newStream(
|
||||||
qpdf, objid, generation, stream_dict, offset, length);
|
qpdf, objid, generation, stream_dict, offset, length);
|
||||||
@ -1352,8 +1371,10 @@ class QPDFObjectHandle
|
|||||||
class ObjAccessor
|
class ObjAccessor
|
||||||
{
|
{
|
||||||
friend class QPDF;
|
friend class QPDF;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static PointerHolder<QPDFObject> getObject(QPDFObjectHandle& o)
|
static PointerHolder<QPDFObject>
|
||||||
|
getObject(QPDFObjectHandle& o)
|
||||||
{
|
{
|
||||||
o.dereference();
|
o.dereference();
|
||||||
return o.obj;
|
return o.obj;
|
||||||
@ -1368,8 +1389,10 @@ class QPDFObjectHandle
|
|||||||
friend class QPDF_Dictionary;
|
friend class QPDF_Dictionary;
|
||||||
friend class QPDF_Stream;
|
friend class QPDF_Stream;
|
||||||
friend class SparseOHArray;
|
friend class SparseOHArray;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void releaseResolved(QPDFObjectHandle& o)
|
static void
|
||||||
|
releaseResolved(QPDFObjectHandle& o)
|
||||||
{
|
{
|
||||||
o.releaseResolved();
|
o.releaseResolved();
|
||||||
}
|
}
|
||||||
@ -1433,14 +1456,13 @@ class QPDFObjectHandle
|
|||||||
// Indicate if this is an image. If exclude_imagemask is true,
|
// Indicate if this is an image. If exclude_imagemask is true,
|
||||||
// don't count image masks as images.
|
// don't count image masks as images.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool isImage(bool exclude_imagemask=true);
|
bool isImage(bool exclude_imagemask = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDFObjectHandle(QPDF*, int objid, int generation);
|
QPDFObjectHandle(QPDF*, int objid, int generation);
|
||||||
QPDFObjectHandle(QPDFObject*);
|
QPDFObjectHandle(QPDFObject*);
|
||||||
|
|
||||||
enum parser_state_e
|
enum parser_state_e {
|
||||||
{
|
|
||||||
st_top,
|
st_top,
|
||||||
st_start,
|
st_start,
|
||||||
st_stop,
|
st_stop,
|
||||||
@ -1452,31 +1474,41 @@ class QPDFObjectHandle
|
|||||||
// Private object factory methods
|
// Private object factory methods
|
||||||
static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation);
|
static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation);
|
||||||
static QPDFObjectHandle newStream(
|
static QPDFObjectHandle newStream(
|
||||||
QPDF* qpdf, int objid, int generation,
|
QPDF* qpdf,
|
||||||
QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length);
|
int objid,
|
||||||
|
int generation,
|
||||||
|
QPDFObjectHandle stream_dict,
|
||||||
|
qpdf_offset_t offset,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
void typeWarning(char const* expected_type,
|
void typeWarning(char const* expected_type, std::string const& warning);
|
||||||
std::string const& warning);
|
|
||||||
void objectWarning(std::string const& warning);
|
void objectWarning(std::string const& warning);
|
||||||
void assertType(char const* type_name, bool istype);
|
void assertType(char const* type_name, bool istype);
|
||||||
void dereference();
|
void dereference();
|
||||||
void copyObject(std::set<QPDFObjGen>& visited, bool cross_indirect,
|
void copyObject(
|
||||||
bool first_level_only, bool stop_at_streams);
|
std::set<QPDFObjGen>& visited,
|
||||||
|
bool cross_indirect,
|
||||||
|
bool first_level_only,
|
||||||
|
bool stop_at_streams);
|
||||||
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
|
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
|
||||||
void releaseResolved();
|
void releaseResolved();
|
||||||
static void setObjectDescriptionFromInput(
|
static void setObjectDescriptionFromInput(
|
||||||
QPDFObjectHandle, QPDF*, std::string const&,
|
QPDFObjectHandle,
|
||||||
PointerHolder<InputSource>, qpdf_offset_t);
|
QPDF*,
|
||||||
|
std::string const&,
|
||||||
|
PointerHolder<InputSource>,
|
||||||
|
qpdf_offset_t);
|
||||||
static QPDFObjectHandle parseInternal(
|
static QPDFObjectHandle parseInternal(
|
||||||
PointerHolder<InputSource> input,
|
PointerHolder<InputSource> input,
|
||||||
std::string const& object_description,
|
std::string const& object_description,
|
||||||
QPDFTokenizer& tokenizer, bool& empty,
|
QPDFTokenizer& tokenizer,
|
||||||
StringDecrypter* decrypter, QPDF* context,
|
bool& empty,
|
||||||
|
StringDecrypter* decrypter,
|
||||||
|
QPDF* context,
|
||||||
bool content_stream);
|
bool content_stream);
|
||||||
void setParsedOffset(qpdf_offset_t offset);
|
void setParsedOffset(qpdf_offset_t offset);
|
||||||
void parseContentStream_internal(
|
void parseContentStream_internal(
|
||||||
std::string const& description,
|
std::string const& description, ParserCallbacks* callbacks);
|
||||||
ParserCallbacks* callbacks);
|
|
||||||
static void parseContentStream_data(
|
static void parseContentStream_data(
|
||||||
PointerHolder<Buffer>,
|
PointerHolder<Buffer>,
|
||||||
std::string const& description,
|
std::string const& description,
|
||||||
@ -1493,7 +1525,7 @@ class QPDFObjectHandle
|
|||||||
// a substantial performance penalty since QPDFObjectHandle
|
// a substantial performance penalty since QPDFObjectHandle
|
||||||
// objects are copied around so frequently.
|
// objects are copied around so frequently.
|
||||||
QPDF* qpdf;
|
QPDF* qpdf;
|
||||||
int objid; // 0 for direct object
|
int objid; // 0 for direct object
|
||||||
int generation;
|
int generation;
|
||||||
PointerHolder<QPDFObject> obj;
|
PointerHolder<QPDFObject> obj;
|
||||||
bool reserved;
|
bool reserved;
|
||||||
@ -1507,7 +1539,7 @@ class QPDFObjectHandle
|
|||||||
// If this is causing problems in your code, define
|
// If this is causing problems in your code, define
|
||||||
// QPDF_NO_QPDF_STRING to prevent the declaration from being here.
|
// QPDF_NO_QPDF_STRING to prevent the declaration from being here.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
|
QPDFObjectHandle operator""_qpdf(char const* v, size_t len);
|
||||||
#endif // QPDF_NO_QPDF_STRING
|
#endif // QPDF_NO_QPDF_STRING
|
||||||
|
|
||||||
class QPDFObjectHandle::QPDFDictItems
|
class QPDFObjectHandle::QPDFDictItems
|
||||||
@ -1531,6 +1563,7 @@ class QPDFObjectHandle::QPDFDictItems
|
|||||||
class iterator
|
class iterator
|
||||||
{
|
{
|
||||||
friend class QPDFDictItems;
|
friend class QPDFDictItems;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::pair<std::string, QPDFObjectHandle> T;
|
typedef std::pair<std::string, QPDFObjectHandle> T;
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
@ -1544,7 +1577,8 @@ class QPDFObjectHandle::QPDFDictItems
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator++();
|
iterator& operator++();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator++(int)
|
iterator
|
||||||
|
operator++(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@ -1553,7 +1587,8 @@ class QPDFObjectHandle::QPDFDictItems
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator--();
|
iterator& operator--();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator--(int)
|
iterator
|
||||||
|
operator--(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@ -1566,9 +1601,10 @@ class QPDFObjectHandle::QPDFDictItems
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator==(iterator const& other) const;
|
bool operator==(iterator const& other) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(iterator const& other) const
|
bool
|
||||||
|
operator!=(iterator const& other) const
|
||||||
{
|
{
|
||||||
return ! operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1626,6 +1662,7 @@ class QPDFObjectHandle::QPDFArrayItems
|
|||||||
class iterator
|
class iterator
|
||||||
{
|
{
|
||||||
friend class QPDFArrayItems;
|
friend class QPDFArrayItems;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef QPDFObjectHandle T;
|
typedef QPDFObjectHandle T;
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
@ -1639,7 +1676,8 @@ class QPDFObjectHandle::QPDFArrayItems
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator++();
|
iterator& operator++();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator++(int)
|
iterator
|
||||||
|
operator++(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@ -1648,7 +1686,8 @@ class QPDFObjectHandle::QPDFArrayItems
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator& operator--();
|
iterator& operator--();
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
iterator operator--(int)
|
iterator
|
||||||
|
operator--(int)
|
||||||
{
|
{
|
||||||
iterator t = *this;
|
iterator t = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@ -1661,9 +1700,10 @@ class QPDFObjectHandle::QPDFArrayItems
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator==(iterator const& other) const;
|
bool operator==(iterator const& other) const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool operator!=(iterator const& other) const
|
bool
|
||||||
|
operator!=(iterator const& other) const
|
||||||
{
|
{
|
||||||
return ! operator==(other);
|
return !operator==(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1700,5 +1740,4 @@ class QPDFObjectHandle::QPDFArrayItems
|
|||||||
QPDFObjectHandle oh;
|
QPDFObjectHandle oh;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // QPDFOBJECTHANDLE_HH
|
#endif // QPDFOBJECTHANDLE_HH
|
||||||
|
@ -50,12 +50,14 @@ class QPDFObjectHelper
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle getObjectHandle()
|
QPDFObjectHandle
|
||||||
|
getObjectHandle()
|
||||||
{
|
{
|
||||||
return this->oh;
|
return this->oh;
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle const getObjectHandle() const
|
QPDFObjectHandle const
|
||||||
|
getObjectHandle() const
|
||||||
{
|
{
|
||||||
return this->oh;
|
return this->oh;
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
#define QPDFOUTLINEDOCUMENTHELPER_HH
|
#define QPDFOUTLINEDOCUMENTHELPER_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFDocumentHelper.hh>
|
#include <qpdf/QPDFDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFOutlineObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFNameTreeObjectHelper.hh>
|
#include <qpdf/QPDFNameTreeObjectHelper.hh>
|
||||||
|
#include <qpdf/QPDFOutlineObjectHelper.hh>
|
||||||
|
|
||||||
#include <qpdf/QPDF.hh>
|
#include <qpdf/QPDF.hh>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -58,8 +58,7 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
|
|||||||
// the name tree pointed to by the /Dests key of the names
|
// the name tree pointed to by the /Dests key of the names
|
||||||
// dictionary.
|
// dictionary.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle resolveNamedDest(QPDFObjectHandle name);
|
||||||
resolveNamedDest(QPDFObjectHandle name);
|
|
||||||
|
|
||||||
// Return a list outlines that are known to target the specified
|
// Return a list outlines that are known to target the specified
|
||||||
// page
|
// page
|
||||||
@ -99,7 +98,7 @@ class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
|
|||||||
std::set<QPDFObjGen> seen;
|
std::set<QPDFObjGen> seen;
|
||||||
QPDFObjectHandle dest_dict;
|
QPDFObjectHandle dest_dict;
|
||||||
PointerHolder<QPDFNameTreeObjectHelper> names_dest;
|
PointerHolder<QPDFNameTreeObjectHelper> names_dest;
|
||||||
std::map<QPDFObjGen, std::vector<QPDFOutlineObjectHelper> > by_page;
|
std::map<QPDFObjGen, std::vector<QPDFOutlineObjectHelper>> by_page;
|
||||||
};
|
};
|
||||||
|
|
||||||
PointerHolder<Members> m;
|
PointerHolder<Members> m;
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#ifndef QPDFOUTLINEOBJECTHELPER_HH
|
#ifndef QPDFOUTLINEOBJECTHELPER_HH
|
||||||
#define QPDFOUTLINEOBJECTHELPER_HH
|
#define QPDFOUTLINEOBJECTHELPER_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFObjGen.hh>
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
|
#include <qpdf/QPDFObjectHelper.hh>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class QPDFOutlineDocumentHelper;
|
class QPDFOutlineDocumentHelper;
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
#ifndef QPDFPAGEDOCUMENTHELPER_HH
|
#ifndef QPDFPAGEDOCUMENTHELPER_HH
|
||||||
#define QPDFPAGEDOCUMENTHELPER_HH
|
#define QPDFPAGEDOCUMENTHELPER_HH
|
||||||
|
|
||||||
|
#include <qpdf/Constants.h>
|
||||||
#include <qpdf/QPDFDocumentHelper.hh>
|
#include <qpdf/QPDFDocumentHelper.hh>
|
||||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||||
#include <qpdf/Constants.h>
|
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
@ -106,8 +106,10 @@ class QPDFPageDocumentHelper: public QPDFDocumentHelper
|
|||||||
// Add new page before or after refpage. See comments for addPage
|
// Add new page before or after refpage. See comments for addPage
|
||||||
// for details about what newpage should be.
|
// for details about what newpage should be.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void addPageAt(QPDFPageObjectHelper newpage, bool before,
|
void addPageAt(
|
||||||
QPDFPageObjectHelper refpage);
|
QPDFPageObjectHelper newpage,
|
||||||
|
bool before,
|
||||||
|
QPDFPageObjectHelper refpage);
|
||||||
|
|
||||||
// Remove page from the pdf.
|
// Remove page from the pdf.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -126,8 +128,7 @@ class QPDFPageDocumentHelper: public QPDFDocumentHelper
|
|||||||
// those flags.
|
// those flags.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void flattenAnnotations(
|
void flattenAnnotations(
|
||||||
int required_flags = 0,
|
int required_flags = 0, int forbidden_flags = an_invisible | an_hidden);
|
||||||
int forbidden_flags = an_invisible | an_hidden);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void flattenAnnotationsForPage(
|
void flattenAnnotationsForPage(
|
||||||
|
@ -77,10 +77,11 @@ class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper
|
|||||||
// behavior facilitates using this function to incrementally build
|
// behavior facilitates using this function to incrementally build
|
||||||
// up a page labels tree when merging files.
|
// up a page labels tree when merging files.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void
|
void getLabelsForPageRange(
|
||||||
getLabelsForPageRange(long long start_idx, long long end_idx,
|
long long start_idx,
|
||||||
long long new_start_idx,
|
long long end_idx,
|
||||||
std::vector<QPDFObjectHandle>& new_labels);
|
long long new_start_idx,
|
||||||
|
std::vector<QPDFObjectHandle>& new_labels);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Members
|
class Members
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
#ifndef QPDFPAGEOBJECTHELPER_HH
|
#ifndef QPDFPAGEOBJECTHELPER_HH
|
||||||
#define QPDFPAGEOBJECTHELPER_HH
|
#define QPDFPAGEOBJECTHELPER_HH
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHelper.hh>
|
|
||||||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||||
#include <qpdf/QPDFMatrix.hh>
|
#include <qpdf/QPDFMatrix.hh>
|
||||||
|
#include <qpdf/QPDFObjectHelper.hh>
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
@ -57,23 +57,19 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// going to modify the returned object and want the modifications
|
// going to modify the returned object and want the modifications
|
||||||
// to apply to the current page/form XObject only.
|
// to apply to the current page/form XObject only.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle getAttribute(std::string const& name, bool copy_if_shared);
|
||||||
getAttribute(std::string const& name, bool copy_if_shared);
|
|
||||||
|
|
||||||
// Return the TrimBox. If not defined, fall back to CropBox
|
// Return the TrimBox. If not defined, fall back to CropBox
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle getTrimBox(bool copy_if_shared = false);
|
||||||
getTrimBox(bool copy_if_shared = false);
|
|
||||||
|
|
||||||
// Return the CropBox. If not defined, fall back to MediaBox
|
// Return the CropBox. If not defined, fall back to MediaBox
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle getCropBox(bool copy_if_shared = false);
|
||||||
getCropBox(bool copy_if_shared = false);
|
|
||||||
|
|
||||||
// Return the MediaBox
|
// Return the MediaBox
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle getMediaBox(bool copy_if_shared = false);
|
||||||
getMediaBox(bool copy_if_shared = false);
|
|
||||||
|
|
||||||
// Iterate through XObjects, possibly recursing into form
|
// Iterate through XObjects, possibly recursing into form
|
||||||
// XObjects. This works with pages or form XObjects. Call action
|
// XObjects. This works with pages or form XObjects. Call action
|
||||||
@ -86,24 +82,27 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void forEachXObject(
|
void forEachXObject(
|
||||||
bool recursive,
|
bool recursive,
|
||||||
std::function<void(QPDFObjectHandle& obj,
|
std::function<void(
|
||||||
QPDFObjectHandle& xobj_dict,
|
QPDFObjectHandle& obj,
|
||||||
std::string const& key)> action,
|
QPDFObjectHandle& xobj_dict,
|
||||||
std::function<bool(QPDFObjectHandle)> selector=nullptr);
|
std::string const& key)> action,
|
||||||
|
std::function<bool(QPDFObjectHandle)> selector = nullptr);
|
||||||
// Only call action for images
|
// Only call action for images
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void forEachImage(
|
void forEachImage(
|
||||||
bool recursive,
|
bool recursive,
|
||||||
std::function<void(QPDFObjectHandle& obj,
|
std::function<void(
|
||||||
QPDFObjectHandle& xobj_dict,
|
QPDFObjectHandle& obj,
|
||||||
std::string const& key)> action);
|
QPDFObjectHandle& xobj_dict,
|
||||||
|
std::string const& key)> action);
|
||||||
// Only call action for form XObjects
|
// Only call action for form XObjects
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void forEachFormXObject(
|
void forEachFormXObject(
|
||||||
bool recursive,
|
bool recursive,
|
||||||
std::function<void(QPDFObjectHandle& obj,
|
std::function<void(
|
||||||
QPDFObjectHandle& xobj_dict,
|
QPDFObjectHandle& obj,
|
||||||
std::string const& key)> action);
|
QPDFObjectHandle& xobj_dict,
|
||||||
|
std::string const& key)> action);
|
||||||
|
|
||||||
// Returns an empty map if there are no images or no resources.
|
// Returns an empty map if there are no images or no resources.
|
||||||
// Prior to qpdf 8.4.0, this function did not support inherited
|
// Prior to qpdf 8.4.0, this function did not support inherited
|
||||||
@ -142,8 +141,8 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// only_subtype is non-empty, only include annotations of the
|
// only_subtype is non-empty, only include annotations of the
|
||||||
// given subtype.
|
// given subtype.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::vector<QPDFAnnotationObjectHelper> getAnnotations(
|
std::vector<QPDFAnnotationObjectHelper>
|
||||||
std::string const& only_subtype = "");
|
getAnnotations(std::string const& only_subtype = "");
|
||||||
|
|
||||||
// Returns a vector of stream objects representing the content
|
// Returns a vector of stream objects representing the content
|
||||||
// streams for the given page. This routine allows the caller to
|
// streams for the given page. This routine allows the caller to
|
||||||
@ -203,13 +202,13 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// contents, as happens with addContentTokenFilter. See
|
// contents, as happens with addContentTokenFilter. See
|
||||||
// examples/pdf-count-strings.cc for an example.
|
// examples/pdf-count-strings.cc for an example.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void filterContents(QPDFObjectHandle::TokenFilter* filter,
|
void
|
||||||
Pipeline* next = 0);
|
filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = 0);
|
||||||
|
|
||||||
// Old name -- calls filterContents()
|
// Old name -- calls filterContents()
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void filterPageContents(QPDFObjectHandle::TokenFilter* filter,
|
void filterPageContents(
|
||||||
Pipeline* next = 0);
|
QPDFObjectHandle::TokenFilter* filter, Pipeline* next = 0);
|
||||||
|
|
||||||
// Pipe a page's contents through the given pipeline. This method
|
// Pipe a page's contents through the given pipeline. This method
|
||||||
// works whether the contents are a single stream or an array of
|
// works whether the contents are a single stream or an array of
|
||||||
@ -303,7 +302,8 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// behavior.
|
// behavior.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string placeFormXObject(
|
std::string placeFormXObject(
|
||||||
QPDFObjectHandle fo, std::string const& name,
|
QPDFObjectHandle fo,
|
||||||
|
std::string const& name,
|
||||||
QPDFObjectHandle::Rectangle rect,
|
QPDFObjectHandle::Rectangle rect,
|
||||||
bool invert_transformations = true,
|
bool invert_transformations = true,
|
||||||
bool allow_shrink = true,
|
bool allow_shrink = true,
|
||||||
@ -313,7 +313,8 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// matrix that was used.
|
// matrix that was used.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string placeFormXObject(
|
std::string placeFormXObject(
|
||||||
QPDFObjectHandle fo, std::string const& name,
|
QPDFObjectHandle fo,
|
||||||
|
std::string const& name,
|
||||||
QPDFObjectHandle::Rectangle rect,
|
QPDFObjectHandle::Rectangle rect,
|
||||||
QPDFMatrix& cm,
|
QPDFMatrix& cm,
|
||||||
bool invert_transformations = true,
|
bool invert_transformations = true,
|
||||||
@ -326,9 +327,11 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// placeFormXObject.
|
// placeFormXObject.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFMatrix getMatrixForFormXObjectPlacement(
|
QPDFMatrix getMatrixForFormXObjectPlacement(
|
||||||
QPDFObjectHandle fo, QPDFObjectHandle::Rectangle rect,
|
QPDFObjectHandle fo,
|
||||||
|
QPDFObjectHandle::Rectangle rect,
|
||||||
bool invert_transformations = true,
|
bool invert_transformations = true,
|
||||||
bool allow_shrink = true, bool allow_expand = false);
|
bool allow_shrink = true,
|
||||||
|
bool allow_expand = false);
|
||||||
|
|
||||||
// If a page is rotated using /Rotate in the page's dictionary,
|
// If a page is rotated using /Rotate in the page's dictionary,
|
||||||
// instead rotate the page by the same amount by altering the
|
// instead rotate the page by the same amount by altering the
|
||||||
@ -372,13 +375,13 @@ class QPDFPageObjectHelper: public QPDFObjectHelper
|
|||||||
// these outside and pass them in.
|
// these outside and pass them in.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void copyAnnotations(
|
void copyAnnotations(
|
||||||
QPDFPageObjectHelper from_page, QPDFMatrix const& cm = QPDFMatrix(),
|
QPDFPageObjectHelper from_page,
|
||||||
|
QPDFMatrix const& cm = QPDFMatrix(),
|
||||||
QPDFAcroFormDocumentHelper* afdh = nullptr,
|
QPDFAcroFormDocumentHelper* afdh = nullptr,
|
||||||
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
|
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool
|
static bool removeUnreferencedResourcesHelper(
|
||||||
removeUnreferencedResourcesHelper(
|
|
||||||
QPDFPageObjectHelper ph, std::set<std::string>& unresolved);
|
QPDFPageObjectHelper ph, std::set<std::string>& unresolved);
|
||||||
|
|
||||||
class Members
|
class Members
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
#define QPDFSTREAMFILTER_HH
|
#define QPDFSTREAMFILTER_HH
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/Pipeline.hh>
|
#include <qpdf/Pipeline.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
|
|
||||||
class QPDF_DLL_CLASS QPDFStreamFilter
|
class QPDF_DLL_CLASS QPDFStreamFilter
|
||||||
{
|
{
|
||||||
|
@ -22,19 +22,18 @@
|
|||||||
#ifndef QPDFSYSTEMERROR_HH
|
#ifndef QPDFSYSTEMERROR_HH
|
||||||
#define QPDFSYSTEMERROR_HH
|
#define QPDFSYSTEMERROR_HH
|
||||||
|
|
||||||
|
#include <qpdf/Constants.h>
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
#include <qpdf/Constants.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
|
class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFSystemError(std::string const& description,
|
QPDFSystemError(std::string const& description, int system_errno);
|
||||||
int system_errno);
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual ~QPDFSystemError() noexcept;
|
virtual ~QPDFSystemError() noexcept;
|
||||||
|
|
||||||
@ -48,8 +47,8 @@ class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
|
|||||||
int getErrno() const;
|
int getErrno() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string createWhat(std::string const& description,
|
static std::string
|
||||||
int system_errno);
|
createWhat(std::string const& description, int system_errno);
|
||||||
|
|
||||||
// This class does not use the Members pattern to avoid needless
|
// This class does not use the Members pattern to avoid needless
|
||||||
// memory allocations during exception handling.
|
// memory allocations during exception handling.
|
||||||
|
@ -27,9 +27,9 @@
|
|||||||
#include <qpdf/InputSource.hh>
|
#include <qpdf/InputSource.hh>
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class QPDFTokenizer
|
class QPDFTokenizer
|
||||||
{
|
{
|
||||||
@ -38,8 +38,7 @@ class QPDFTokenizer
|
|||||||
// the tokenizer. tt_eof was introduced in QPDF version 4.1.
|
// the tokenizer. tt_eof was introduced in QPDF version 4.1.
|
||||||
// tt_space, tt_comment, and tt_inline_image were added in QPDF
|
// tt_space, tt_comment, and tt_inline_image were added in QPDF
|
||||||
// version 8.
|
// version 8.
|
||||||
enum token_type_e
|
enum token_type_e {
|
||||||
{
|
|
||||||
tt_bad,
|
tt_bad,
|
||||||
tt_array_close,
|
tt_array_close,
|
||||||
tt_array_open,
|
tt_array_open,
|
||||||
@ -63,39 +62,50 @@ class QPDFTokenizer
|
|||||||
class Token
|
class Token
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Token() : type(tt_bad) {}
|
Token() :
|
||||||
|
type(tt_bad)
|
||||||
|
{
|
||||||
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Token(token_type_e type, std::string const& value);
|
Token(token_type_e type, std::string const& value);
|
||||||
Token(token_type_e type, std::string const& value,
|
Token(
|
||||||
std::string raw_value, std::string error_message) :
|
token_type_e type,
|
||||||
|
std::string const& value,
|
||||||
|
std::string raw_value,
|
||||||
|
std::string error_message) :
|
||||||
type(type),
|
type(type),
|
||||||
value(value),
|
value(value),
|
||||||
raw_value(raw_value),
|
raw_value(raw_value),
|
||||||
error_message(error_message)
|
error_message(error_message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
token_type_e getType() const
|
token_type_e
|
||||||
|
getType() const
|
||||||
{
|
{
|
||||||
return this->type;
|
return this->type;
|
||||||
}
|
}
|
||||||
std::string const& getValue() const
|
std::string const&
|
||||||
|
getValue() const
|
||||||
{
|
{
|
||||||
return this->value;
|
return this->value;
|
||||||
}
|
}
|
||||||
std::string const& getRawValue() const
|
std::string const&
|
||||||
|
getRawValue() const
|
||||||
{
|
{
|
||||||
return this->raw_value;
|
return this->raw_value;
|
||||||
}
|
}
|
||||||
std::string const& getErrorMessage() const
|
std::string const&
|
||||||
|
getErrorMessage() const
|
||||||
{
|
{
|
||||||
return this->error_message;
|
return this->error_message;
|
||||||
}
|
}
|
||||||
bool operator==(Token const& rhs) const
|
bool
|
||||||
|
operator==(Token const& rhs) const
|
||||||
{
|
{
|
||||||
// Ignore fields other than type and value
|
// Ignore fields other than type and value
|
||||||
return ((this->type != tt_bad) &&
|
return (
|
||||||
(this->type == rhs.type) &&
|
(this->type != tt_bad) && (this->type == rhs.type) &&
|
||||||
(this->value == rhs.value));
|
(this->value == rhs.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -162,10 +172,11 @@ class QPDFTokenizer
|
|||||||
// offset" as returned by input->getLastOffset() points to the
|
// offset" as returned by input->getLastOffset() points to the
|
||||||
// beginning of the token.
|
// beginning of the token.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
Token readToken(PointerHolder<InputSource> input,
|
Token readToken(
|
||||||
std::string const& context,
|
PointerHolder<InputSource> input,
|
||||||
bool allow_bad = false,
|
std::string const& context,
|
||||||
size_t max_len = 0);
|
bool allow_bad = false,
|
||||||
|
size_t max_len = 0);
|
||||||
|
|
||||||
// Calling this method puts the tokenizer in a state for reading
|
// Calling this method puts the tokenizer in a state for reading
|
||||||
// inline images. You should call this method after reading the
|
// inline images. You should call this method after reading the
|
||||||
@ -188,8 +199,16 @@ class QPDFTokenizer
|
|||||||
void findEI(PointerHolder<InputSource> input);
|
void findEI(PointerHolder<InputSource> input);
|
||||||
|
|
||||||
enum state_e {
|
enum state_e {
|
||||||
st_top, st_in_space, st_in_comment, st_in_string, st_lt, st_gt,
|
st_top,
|
||||||
st_literal, st_in_hexstring, st_inline_image, st_token_ready
|
st_in_space,
|
||||||
|
st_in_comment,
|
||||||
|
st_in_string,
|
||||||
|
st_lt,
|
||||||
|
st_gt,
|
||||||
|
st_literal,
|
||||||
|
st_in_hexstring,
|
||||||
|
st_inline_image,
|
||||||
|
st_token_ready
|
||||||
};
|
};
|
||||||
|
|
||||||
class Members
|
class Members
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error
|
class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error
|
||||||
{
|
{
|
||||||
|
@ -29,24 +29,24 @@
|
|||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <qpdf/Constants.h>
|
#include <qpdf/Constants.h>
|
||||||
|
|
||||||
#include <qpdf/QPDFObjectHandle.hh>
|
|
||||||
#include <qpdf/QPDFObjGen.hh>
|
|
||||||
#include <qpdf/QPDFXRefEntry.hh>
|
|
||||||
#include <qpdf/Pl_Buffer.hh>
|
|
||||||
#include <qpdf/PointerHolder.hh>
|
|
||||||
#include <qpdf/Pipeline.hh>
|
|
||||||
#include <qpdf/Buffer.hh>
|
#include <qpdf/Buffer.hh>
|
||||||
#include <qpdf/PDFVersion.hh>
|
#include <qpdf/PDFVersion.hh>
|
||||||
|
#include <qpdf/Pipeline.hh>
|
||||||
|
#include <qpdf/Pl_Buffer.hh>
|
||||||
|
#include <qpdf/PointerHolder.hh>
|
||||||
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
|
#include <qpdf/QPDFObjectHandle.hh>
|
||||||
|
#include <qpdf/QPDFXRefEntry.hh>
|
||||||
|
|
||||||
class QPDF;
|
class QPDF;
|
||||||
class Pl_Count;
|
class Pl_Count;
|
||||||
@ -372,72 +372,104 @@ class QPDFWriter
|
|||||||
// it unless you have to.
|
// it unless you have to.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setR2EncryptionParameters(
|
void setR2EncryptionParameters(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
bool allow_print, bool allow_modify,
|
char const* owner_password,
|
||||||
bool allow_extract, bool allow_annotate);
|
bool allow_print,
|
||||||
|
bool allow_modify,
|
||||||
|
bool allow_extract,
|
||||||
|
bool allow_annotate);
|
||||||
// R3 uses RC4, which is a weak cryptographic algorithm. Don't use
|
// R3 uses RC4, which is a weak cryptographic algorithm. Don't use
|
||||||
// it unless you have to.
|
// it unless you have to.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setR3EncryptionParameters(
|
void setR3EncryptionParameters(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
char const* owner_password,
|
||||||
bool allow_assemble, bool allow_annotate_and_form,
|
bool allow_accessibility,
|
||||||
bool allow_form_filling, bool allow_modify_other,
|
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
|
// R4 uses RC4, which is a weak cryptographic algorithm, when
|
||||||
// use_aes=false. Don't use it unless you have to.
|
// use_aes=false. Don't use it unless you have to.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setR4EncryptionParameters(
|
void setR4EncryptionParameters(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
char const* owner_password,
|
||||||
bool allow_assemble, bool allow_annotate_and_form,
|
bool allow_accessibility,
|
||||||
bool allow_form_filling, bool allow_modify_other,
|
bool allow_extract,
|
||||||
qpdf_r3_print_e print, bool encrypt_metadata, bool use_aes);
|
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);
|
||||||
// R5 is deprecated. Do not use it for production use. Writing
|
// R5 is deprecated. Do not use it for production use. Writing
|
||||||
// R5 is supported by qpdf primarily to generate test files for
|
// R5 is supported by qpdf primarily to generate test files for
|
||||||
// applications that may need to test R5 support.
|
// applications that may need to test R5 support.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setR5EncryptionParameters(
|
void setR5EncryptionParameters(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
char const* owner_password,
|
||||||
bool allow_assemble, bool allow_annotate_and_form,
|
bool allow_accessibility,
|
||||||
bool allow_form_filling, bool allow_modify_other,
|
bool allow_extract,
|
||||||
qpdf_r3_print_e print, bool encrypt_metadata);
|
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_DLL
|
QPDF_DLL
|
||||||
void setR6EncryptionParameters(
|
void setR6EncryptionParameters(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
char const* owner_password,
|
||||||
bool allow_assemble, bool allow_annotate_and_form,
|
bool allow_accessibility,
|
||||||
bool allow_form_filling, bool allow_modify_other,
|
bool allow_extract,
|
||||||
qpdf_r3_print_e print, bool encrypt_metadata_aes);
|
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);
|
||||||
|
|
||||||
// Pre qpdf 8.4.0 API
|
// Pre qpdf 8.4.0 API
|
||||||
[[deprecated("see newer API above")]]
|
[[deprecated("see newer API above")]] QPDF_DLL void
|
||||||
QPDF_DLL
|
setR3EncryptionParameters(
|
||||||
void setR3EncryptionParameters(
|
char const* user_password,
|
||||||
char const* user_password, char const* owner_password,
|
char const* owner_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
bool allow_accessibility,
|
||||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify);
|
bool allow_extract,
|
||||||
[[deprecated("see newer API above")]]
|
qpdf_r3_print_e print,
|
||||||
QPDF_DLL
|
qpdf_r3_modify_e modify);
|
||||||
void setR4EncryptionParameters(
|
[[deprecated("see newer API above")]] QPDF_DLL void
|
||||||
char const* user_password, char const* owner_password,
|
setR4EncryptionParameters(
|
||||||
bool allow_accessibility, bool allow_extract,
|
char const* user_password,
|
||||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
char const* owner_password,
|
||||||
bool encrypt_metadata, bool use_aes);
|
bool allow_accessibility,
|
||||||
[[deprecated("see newer API above")]]
|
bool allow_extract,
|
||||||
QPDF_DLL
|
qpdf_r3_print_e print,
|
||||||
void setR5EncryptionParameters(
|
qpdf_r3_modify_e modify,
|
||||||
char const* user_password, char const* owner_password,
|
bool encrypt_metadata,
|
||||||
bool allow_accessibility, bool allow_extract,
|
bool use_aes);
|
||||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
[[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);
|
bool encrypt_metadata);
|
||||||
[[deprecated("see newer API above")]]
|
[[deprecated("see newer API above")]] QPDF_DLL void
|
||||||
QPDF_DLL
|
setR6EncryptionParameters(
|
||||||
void setR6EncryptionParameters(
|
char const* user_password,
|
||||||
char const* user_password, char const* owner_password,
|
char const* owner_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
bool allow_accessibility,
|
||||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify,
|
bool allow_extract,
|
||||||
|
qpdf_r3_print_e print,
|
||||||
|
qpdf_r3_modify_e modify,
|
||||||
bool encrypt_metadata_aes);
|
bool encrypt_metadata_aes);
|
||||||
|
|
||||||
// Create linearized output. Disables qdf mode, content
|
// Create linearized output. Disables qdf mode, content
|
||||||
@ -496,11 +528,11 @@ class QPDFWriter
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// flags used by unparseObject
|
// flags used by unparseObject
|
||||||
static int const f_stream = 1 << 0;
|
static int const f_stream = 1 << 0;
|
||||||
static int const f_filtered = 1 << 1;
|
static int const f_filtered = 1 << 1;
|
||||||
static int const f_in_ostream = 1 << 2;
|
static int const f_in_ostream = 1 << 2;
|
||||||
static int const f_hex_string = 1 << 3;
|
static int const f_hex_string = 1 << 3;
|
||||||
static int const f_no_encryption = 1 << 4;
|
static int const f_no_encryption = 1 << 4;
|
||||||
|
|
||||||
enum trailer_e { t_normal, t_lin_first, t_lin_second };
|
enum trailer_e { t_normal, t_lin_first, t_lin_second };
|
||||||
|
|
||||||
@ -516,9 +548,9 @@ class QPDFWriter
|
|||||||
class PipelinePopper
|
class PipelinePopper
|
||||||
{
|
{
|
||||||
friend class QPDFWriter;
|
friend class QPDFWriter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PipelinePopper(QPDFWriter* qw,
|
PipelinePopper(QPDFWriter* qw, PointerHolder<Buffer>* bp = 0) :
|
||||||
PointerHolder<Buffer>* bp = 0) :
|
|
||||||
qw(qw),
|
qw(qw),
|
||||||
bp(bp)
|
bp(bp)
|
||||||
{
|
{
|
||||||
@ -545,15 +577,24 @@ class QPDFWriter
|
|||||||
std::vector<qpdf_offset_t>& offsets, int first_obj);
|
std::vector<qpdf_offset_t>& offsets, int first_obj);
|
||||||
void writeObjectStream(QPDFObjectHandle object);
|
void writeObjectStream(QPDFObjectHandle object);
|
||||||
void writeObject(QPDFObjectHandle object, int object_stream_index = -1);
|
void writeObject(QPDFObjectHandle object, int object_stream_index = -1);
|
||||||
void writeTrailer(trailer_e which, int size,
|
void writeTrailer(
|
||||||
bool xref_stream, qpdf_offset_t prev,
|
trailer_e which,
|
||||||
int linearization_pass);
|
int size,
|
||||||
bool willFilterStream(QPDFObjectHandle stream,
|
bool xref_stream,
|
||||||
bool& compress_stream, bool& is_metadata,
|
qpdf_offset_t prev,
|
||||||
PointerHolder<Buffer>* stream_data);
|
int linearization_pass);
|
||||||
void unparseObject(QPDFObjectHandle object, int level, int flags,
|
bool willFilterStream(
|
||||||
// for stream dictionaries
|
QPDFObjectHandle stream,
|
||||||
size_t stream_length = 0, bool compress = false);
|
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);
|
||||||
void unparseChild(QPDFObjectHandle child, int level, int flags);
|
void unparseChild(QPDFObjectHandle child, int level, int flags);
|
||||||
void initializeSpecialStreams();
|
void initializeSpecialStreams();
|
||||||
void preserveObjectStreams();
|
void preserveObjectStreams();
|
||||||
@ -562,23 +603,39 @@ class QPDFWriter
|
|||||||
void generateID();
|
void generateID();
|
||||||
void interpretR3EncryptionParameters(
|
void interpretR3EncryptionParameters(
|
||||||
std::set<int>& bits_to_clear,
|
std::set<int>& bits_to_clear,
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
bool allow_accessibility, bool allow_extract,
|
char const* owner_password,
|
||||||
bool allow_assemble, bool allow_annotate_and_form,
|
bool allow_accessibility,
|
||||||
bool allow_form_filling, bool allow_modify_other,
|
bool allow_extract,
|
||||||
qpdf_r3_print_e print, qpdf_r3_modify_e modify);
|
bool allow_assemble,
|
||||||
void disableIncompatibleEncryption(int major, int minor,
|
bool allow_annotate_and_form,
|
||||||
int extension_level);
|
bool allow_form_filling,
|
||||||
|
bool allow_modify_other,
|
||||||
|
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;
|
void parseVersion(std::string const& version, int& major, int& minor) const;
|
||||||
int compareVersions(int major1, int minor1, int major2, int minor2) const;
|
int compareVersions(int major1, int minor1, int major2, int minor2) const;
|
||||||
void setEncryptionParameters(
|
void setEncryptionParameters(
|
||||||
char const* user_password, char const* owner_password,
|
char const* user_password,
|
||||||
int V, int R, int key_len, std::set<int>& bits_to_clear);
|
char const* owner_password,
|
||||||
|
int V,
|
||||||
|
int R,
|
||||||
|
int key_len,
|
||||||
|
std::set<int>& bits_to_clear);
|
||||||
void setEncryptionParametersInternal(
|
void setEncryptionParametersInternal(
|
||||||
int V, int R, int key_len, int P,
|
int V,
|
||||||
std::string const& O, std::string const& U,
|
int R,
|
||||||
std::string const& OE, std::string const& UE, std::string const& Perms,
|
int key_len,
|
||||||
std::string const& id1, std::string const& user_password,
|
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);
|
std::string const& encryption_key);
|
||||||
void setDataKey(int objid);
|
void setDataKey(int objid);
|
||||||
int openObject(int objid = 0);
|
int openObject(int objid = 0);
|
||||||
@ -595,10 +652,13 @@ class QPDFWriter
|
|||||||
void doWriteSetup();
|
void doWriteSetup();
|
||||||
void writeHeader();
|
void writeHeader();
|
||||||
void writeHintStream(int hint_id);
|
void writeHintStream(int hint_id);
|
||||||
|
qpdf_offset_t
|
||||||
|
writeXRefTable(trailer_e which, int first, int last, int size);
|
||||||
qpdf_offset_t writeXRefTable(
|
qpdf_offset_t writeXRefTable(
|
||||||
trailer_e which, int first, int last, int size);
|
trailer_e which,
|
||||||
qpdf_offset_t writeXRefTable(
|
int first,
|
||||||
trailer_e which, int first, int last, int size,
|
int last,
|
||||||
|
int size,
|
||||||
// for linearization
|
// for linearization
|
||||||
qpdf_offset_t prev,
|
qpdf_offset_t prev,
|
||||||
bool suppress_offsets,
|
bool suppress_offsets,
|
||||||
@ -607,11 +667,21 @@ class QPDFWriter
|
|||||||
qpdf_offset_t hint_length,
|
qpdf_offset_t hint_length,
|
||||||
int linearization_pass);
|
int linearization_pass);
|
||||||
qpdf_offset_t writeXRefStream(
|
qpdf_offset_t writeXRefStream(
|
||||||
int objid, int max_id, qpdf_offset_t max_offset,
|
int objid,
|
||||||
trailer_e which, int first, int last, int size);
|
int max_id,
|
||||||
|
qpdf_offset_t max_offset,
|
||||||
|
trailer_e which,
|
||||||
|
int first,
|
||||||
|
int last,
|
||||||
|
int size);
|
||||||
qpdf_offset_t writeXRefStream(
|
qpdf_offset_t writeXRefStream(
|
||||||
int objid, int max_id, qpdf_offset_t max_offset,
|
int objid,
|
||||||
trailer_e which, int first, int last, int size,
|
int max_id,
|
||||||
|
qpdf_offset_t max_offset,
|
||||||
|
trailer_e which,
|
||||||
|
int first,
|
||||||
|
int last,
|
||||||
|
int size,
|
||||||
// for linearization
|
// for linearization
|
||||||
qpdf_offset_t prev,
|
qpdf_offset_t prev,
|
||||||
int hint_id,
|
int hint_id,
|
||||||
@ -627,7 +697,7 @@ class QPDFWriter
|
|||||||
// popped.
|
// popped.
|
||||||
Pipeline* pushPipeline(Pipeline*);
|
Pipeline* pushPipeline(Pipeline*);
|
||||||
void activatePipelineStack(PipelinePopper&);
|
void activatePipelineStack(PipelinePopper&);
|
||||||
void initializePipelineStack(Pipeline *);
|
void initializePipelineStack(Pipeline*);
|
||||||
|
|
||||||
void adjustAESStreamLength(size_t& length);
|
void adjustAESStreamLength(size_t& length);
|
||||||
void pushEncryptionFilter(PipelinePopper&);
|
void pushEncryptionFilter(PipelinePopper&);
|
||||||
@ -635,8 +705,8 @@ class QPDFWriter
|
|||||||
void pushMD5Pipeline(PipelinePopper&);
|
void pushMD5Pipeline(PipelinePopper&);
|
||||||
void computeDeterministicIDData();
|
void computeDeterministicIDData();
|
||||||
|
|
||||||
void discardGeneration(std::map<QPDFObjGen, int> const& in,
|
void discardGeneration(
|
||||||
std::map<int, int>& out);
|
std::map<QPDFObjGen, int> const& in, std::map<int, int>& out);
|
||||||
|
|
||||||
class Members
|
class Members
|
||||||
{
|
{
|
||||||
@ -681,8 +751,8 @@ class QPDFWriter
|
|||||||
int encryption_V;
|
int encryption_V;
|
||||||
int encryption_R;
|
int encryption_R;
|
||||||
|
|
||||||
std::string id1; // for /ID key of
|
std::string id1; // for /ID key of
|
||||||
std::string id2; // trailer dictionary
|
std::string id2; // trailer dictionary
|
||||||
std::string final_pdf_version;
|
std::string final_pdf_version;
|
||||||
int final_extension_level;
|
int final_extension_level;
|
||||||
std::string min_pdf_version;
|
std::string min_pdf_version;
|
||||||
@ -707,7 +777,7 @@ class QPDFWriter
|
|||||||
std::map<QPDFObjGen, int> page_object_to_seq;
|
std::map<QPDFObjGen, int> page_object_to_seq;
|
||||||
std::map<QPDFObjGen, int> contents_to_page_seq;
|
std::map<QPDFObjGen, int> contents_to_page_seq;
|
||||||
std::map<QPDFObjGen, int> object_to_object_stream;
|
std::map<QPDFObjGen, int> object_to_object_stream;
|
||||||
std::map<int, std::set<QPDFObjGen> > object_stream_to_objects;
|
std::map<int, std::set<QPDFObjGen>> object_stream_to_objects;
|
||||||
std::list<Pipeline*> pipeline_stack;
|
std::list<Pipeline*> pipeline_stack;
|
||||||
unsigned long long next_stack_id;
|
unsigned long long next_stack_id;
|
||||||
bool deterministic_id;
|
bool deterministic_id;
|
||||||
|
@ -42,11 +42,11 @@ class QPDFXRefEntry
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int getType() const;
|
int getType() const;
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_offset_t getOffset() const; // only for type 1
|
qpdf_offset_t getOffset() const; // only for type 1
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int getObjStreamNumber() const; // only for type 2
|
int getObjStreamNumber() const; // only for type 2
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int getObjStreamIndex() const; // only for type 2
|
int getObjStreamIndex() const; // only for type 2
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This class does not use the Members pattern to avoid a memory
|
// This class does not use the Members pattern to avoid a memory
|
||||||
|
@ -28,6 +28,6 @@ namespace QTC
|
|||||||
{
|
{
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void TC(char const* const scope, char const* const ccase, int n = 0);
|
void TC(char const* const scope, char const* const ccase, int n = 0);
|
||||||
};
|
}; // namespace QTC
|
||||||
|
|
||||||
#endif // QTC_HH
|
#endif // QTC_HH
|
||||||
|
@ -23,16 +23,16 @@
|
|||||||
#define QUTIL_HH
|
#define QUTIL_HH
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
#include <string>
|
#include <qpdf/Types.h>
|
||||||
#include <list>
|
|
||||||
#include <vector>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class RandomDataProvider;
|
class RandomDataProvider;
|
||||||
class Pipeline;
|
class Pipeline;
|
||||||
@ -48,16 +48,16 @@ namespace QUtil
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string int_to_string_base(long long, int base, int length = 0);
|
std::string int_to_string_base(long long, int base, int length = 0);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string uint_to_string_base(unsigned long long, int base,
|
std::string
|
||||||
int length = 0);
|
uint_to_string_base(unsigned long long, int base, int length = 0);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string double_to_string(double, int decimal_places = 0);
|
std::string double_to_string(double, int decimal_places = 0);
|
||||||
// ABI: combine with other double_to_string by adding
|
// ABI: combine with other double_to_string by adding
|
||||||
// trim_trailing_zeroes above as an optional parameter with a
|
// trim_trailing_zeroes above as an optional parameter with a
|
||||||
// default of true.
|
// default of true.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string double_to_string(double, int decimal_places,
|
std::string
|
||||||
bool trim_trailing_zeroes);
|
double_to_string(double, int decimal_places, bool trim_trailing_zeroes);
|
||||||
|
|
||||||
// These string to number methods throw std::runtime_error on
|
// These string to number methods throw std::runtime_error on
|
||||||
// underflow/overflow.
|
// underflow/overflow.
|
||||||
@ -217,8 +217,14 @@ namespace QUtil
|
|||||||
QPDFTime() = default;
|
QPDFTime() = default;
|
||||||
QPDFTime(QPDFTime const&) = default;
|
QPDFTime(QPDFTime const&) = default;
|
||||||
QPDFTime& operator=(QPDFTime const&) = default;
|
QPDFTime& operator=(QPDFTime const&) = default;
|
||||||
QPDFTime(int year, int month, int day, int hour,
|
QPDFTime(
|
||||||
int minute, int second, int tz_delta) :
|
int year,
|
||||||
|
int month,
|
||||||
|
int day,
|
||||||
|
int hour,
|
||||||
|
int minute,
|
||||||
|
int second,
|
||||||
|
int tz_delta) :
|
||||||
year(year),
|
year(year),
|
||||||
month(month),
|
month(month),
|
||||||
day(day),
|
day(day),
|
||||||
@ -228,13 +234,13 @@ namespace QUtil
|
|||||||
tz_delta(tz_delta)
|
tz_delta(tz_delta)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
int year; // actual year, no 1900 stuff
|
int year; // actual year, no 1900 stuff
|
||||||
int month; // 1--12
|
int month; // 1--12
|
||||||
int day; // 1--31
|
int day; // 1--31
|
||||||
int hour;
|
int hour;
|
||||||
int minute;
|
int minute;
|
||||||
int second;
|
int second;
|
||||||
int tz_delta; // minutes before UTC
|
int tz_delta; // minutes before UTC
|
||||||
};
|
};
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -284,17 +290,16 @@ namespace QUtil
|
|||||||
// encoding system by replacing all unsupported characters with
|
// encoding system by replacing all unsupported characters with
|
||||||
// the given unknown_char.
|
// the given unknown_char.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string utf8_to_ascii(
|
std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?');
|
||||||
std::string const& utf8, char unknown_char = '?');
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string utf8_to_win_ansi(
|
std::string
|
||||||
std::string const& utf8, char unknown_char = '?');
|
utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?');
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string utf8_to_mac_roman(
|
std::string
|
||||||
std::string const& utf8, char unknown_char = '?');
|
utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?');
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string utf8_to_pdf_doc(
|
std::string
|
||||||
std::string const& utf8, char unknown_char = '?');
|
utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?');
|
||||||
|
|
||||||
// These versions return true if the conversion was successful and
|
// These versions return true if the conversion was successful and
|
||||||
// false if any unrepresentable characters were found and had to
|
// false if any unrepresentable characters were found and had to
|
||||||
@ -338,10 +343,11 @@ namespace QUtil
|
|||||||
// the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and just
|
// the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and just
|
||||||
// about everything else) accepts UTF-16LE (as of 10.6.2).
|
// about everything else) accepts UTF-16LE (as of 10.6.2).
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void analyze_encoding(std::string const& str,
|
void analyze_encoding(
|
||||||
bool& has_8bit_chars,
|
std::string const& str,
|
||||||
bool& is_valid_utf8,
|
bool& has_8bit_chars,
|
||||||
bool& is_utf16);
|
bool& is_valid_utf8,
|
||||||
|
bool& is_utf16);
|
||||||
|
|
||||||
// Try to compensate for previously incorrectly encoded strings.
|
// Try to compensate for previously incorrectly encoded strings.
|
||||||
// We want to compensate for the following errors:
|
// We want to compensate for the following errors:
|
||||||
@ -398,14 +404,14 @@ namespace QUtil
|
|||||||
// Filename is UTF-8 encoded, even on Windows, as described in the
|
// Filename is UTF-8 encoded, even on Windows, as described in the
|
||||||
// comments for safe_fopen.
|
// comments for safe_fopen.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::list<std::string> read_lines_from_file(
|
std::list<std::string>
|
||||||
char const* filename, bool preserve_eol = false);
|
read_lines_from_file(char const* filename, bool preserve_eol = false);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::list<std::string> read_lines_from_file(
|
std::list<std::string>
|
||||||
std::istream&, bool preserve_eol = false);
|
read_lines_from_file(std::istream&, bool preserve_eol = false);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::list<std::string> read_lines_from_file(
|
std::list<std::string>
|
||||||
FILE*, bool preserve_eol = false);
|
read_lines_from_file(FILE*, bool preserve_eol = false);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void read_lines_from_file(
|
void read_lines_from_file(
|
||||||
std::function<bool(char&)> next_char,
|
std::function<bool(char&)> next_char,
|
||||||
@ -420,7 +426,7 @@ namespace QUtil
|
|||||||
// platforms, so we have to give it a name that is not likely to
|
// platforms, so we have to give it a name that is not likely to
|
||||||
// be a macro anywhere.
|
// be a macro anywhere.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int str_compare_nocase(char const *, char const *);
|
int str_compare_nocase(char const*, char const*);
|
||||||
|
|
||||||
// These routines help the tokenizer recognize certain character
|
// These routines help the tokenizer recognize certain character
|
||||||
// classes without using ctype, which we avoid because of locale
|
// classes without using ctype, which we avoid because of locale
|
||||||
@ -454,13 +460,13 @@ namespace QUtil
|
|||||||
// another main.
|
// another main.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int call_main_from_wmain(
|
int call_main_from_wmain(
|
||||||
int argc, wchar_t* argv[],
|
int argc, wchar_t* argv[], std::function<int(int, char*[])> realmain);
|
||||||
std::function<int(int, char*[])> realmain);
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int call_main_from_wmain(
|
int call_main_from_wmain(
|
||||||
int argc, wchar_t const* const argv[],
|
int argc,
|
||||||
|
wchar_t const* const argv[],
|
||||||
std::function<int(int, char const* const[])> realmain);
|
std::function<int(int, char const* const[])> realmain);
|
||||||
#endif // QPDF_NO_WCHAR_T
|
#endif // QPDF_NO_WCHAR_T
|
||||||
};
|
}; // namespace QUtil
|
||||||
|
|
||||||
#endif // QUTIL_HH
|
#endif // QUTIL_HH
|
||||||
|
@ -137,9 +137,9 @@
|
|||||||
* https://github.com/qpdf/qpdf/issues/new.
|
* https://github.com/qpdf/qpdf/issues/new.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <qpdf/Constants.h>
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/Types.h>
|
#include <qpdf/Types.h>
|
||||||
#include <qpdf/Constants.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -154,13 +154,13 @@ extern "C" {
|
|||||||
* that the values below can be logically orred together.
|
* that the values below can be logically orred together.
|
||||||
*/
|
*/
|
||||||
typedef int QPDF_ERROR_CODE;
|
typedef int QPDF_ERROR_CODE;
|
||||||
# define QPDF_SUCCESS 0
|
#define QPDF_SUCCESS 0
|
||||||
# define QPDF_WARNINGS 1 << 0
|
#define QPDF_WARNINGS 1 << 0
|
||||||
# define QPDF_ERRORS 1 << 1
|
#define QPDF_ERRORS 1 << 1
|
||||||
|
|
||||||
typedef int QPDF_BOOL;
|
typedef int QPDF_BOOL;
|
||||||
# define QPDF_TRUE 1
|
#define QPDF_TRUE 1
|
||||||
# define QPDF_FALSE 0
|
#define QPDF_FALSE 0
|
||||||
|
|
||||||
/* From qpdf 10.5: call this method to signal to the library that
|
/* From qpdf 10.5: call this method to signal to the library that
|
||||||
* you are explicitly handling errors from functions that don't
|
* you are explicitly handling errors from functions that don't
|
||||||
@ -273,8 +273,8 @@ extern "C" {
|
|||||||
* pointer or an empty string as the password.
|
* pointer or an empty string as the password.
|
||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
|
QPDF_ERROR_CODE
|
||||||
char const* password);
|
qpdf_read(qpdf_data qpdf, char const* filename, char const* password);
|
||||||
|
|
||||||
/* Calling qpdf_read_memory causes processMemoryFile to be called
|
/* Calling qpdf_read_memory causes processMemoryFile to be called
|
||||||
* in the C++ API. Otherwise, it behaves in the same way as
|
* in the C++ API. Otherwise, it behaves in the same way as
|
||||||
@ -283,11 +283,12 @@ extern "C" {
|
|||||||
* library.
|
* library.
|
||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf,
|
QPDF_ERROR_CODE qpdf_read_memory(
|
||||||
char const* description,
|
qpdf_data qpdf,
|
||||||
char const* buffer,
|
char const* description,
|
||||||
unsigned long long size,
|
char const* buffer,
|
||||||
char const* password);
|
unsigned long long size,
|
||||||
|
char const* password);
|
||||||
|
|
||||||
/* Calling qpdf_empty_pdf initializes this qpdf object with an
|
/* Calling qpdf_empty_pdf initializes this qpdf object with an
|
||||||
* empty PDF, making it possible to create a PDF from scratch
|
* empty PDF, making it possible to create a PDF from scratch
|
||||||
@ -409,24 +410,23 @@ extern "C" {
|
|||||||
unsigned char const* qpdf_get_buffer(qpdf_data qpdf);
|
unsigned char const* qpdf_get_buffer(qpdf_data qpdf);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_object_stream_mode(qpdf_data qpdf,
|
void
|
||||||
enum qpdf_object_stream_e mode);
|
qpdf_set_object_stream_mode(qpdf_data qpdf, enum qpdf_object_stream_e mode);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_stream_data_mode(qpdf_data qpdf,
|
void
|
||||||
enum qpdf_stream_data_e mode);
|
qpdf_set_stream_data_mode(qpdf_data qpdf, enum qpdf_stream_data_e mode);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value);
|
void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value);
|
||||||
|
|
||||||
|
QPDF_DLL
|
||||||
|
void qpdf_set_decode_level(
|
||||||
|
qpdf_data qpdf, enum qpdf_stream_decode_level_e level);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_decode_level(qpdf_data qpdf,
|
void
|
||||||
enum qpdf_stream_decode_level_e level);
|
qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value);
|
||||||
|
|
||||||
QPDF_DLL
|
|
||||||
void qpdf_set_preserve_unreferenced_objects(
|
|
||||||
qpdf_data qpdf, QPDF_BOOL value);
|
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value);
|
void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value);
|
||||||
@ -453,77 +453,120 @@ extern "C" {
|
|||||||
void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value);
|
void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_suppress_original_object_IDs(
|
void qpdf_set_suppress_original_object_IDs(qpdf_data qpdf, QPDF_BOOL value);
|
||||||
qpdf_data qpdf, QPDF_BOOL value);
|
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value);
|
void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_r2_encryption_parameters(
|
void qpdf_set_r2_encryption_parameters(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_print, QPDF_BOOL allow_modify,
|
char const* user_password,
|
||||||
QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate);
|
char const* owner_password,
|
||||||
|
QPDF_BOOL allow_print,
|
||||||
|
QPDF_BOOL allow_modify,
|
||||||
|
QPDF_BOOL allow_extract,
|
||||||
|
QPDF_BOOL allow_annotate);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_r3_encryption_parameters2(
|
void qpdf_set_r3_encryption_parameters2(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
char const* owner_password,
|
||||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
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
|
QPDF_DLL
|
||||||
void qpdf_set_r4_encryption_parameters2(
|
void qpdf_set_r4_encryption_parameters2(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
char const* owner_password,
|
||||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
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_BOOL encrypt_metadata,
|
||||||
|
QPDF_BOOL use_aes);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_r5_encryption_parameters2(
|
void qpdf_set_r5_encryption_parameters2(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
char const* owner_password,
|
||||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
QPDF_BOOL allow_accessibility,
|
||||||
enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
|
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);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_r6_encryption_parameters2(
|
void qpdf_set_r6_encryption_parameters2(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
|
char const* owner_password,
|
||||||
QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
|
QPDF_BOOL allow_accessibility,
|
||||||
enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
|
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);
|
||||||
|
|
||||||
/* Pre 8.4.0 encryption API */
|
/* Pre 8.4.0 encryption API */
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_r3_encryption_parameters(
|
void qpdf_set_r3_encryption_parameters(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify);
|
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
|
QPDF_DLL
|
||||||
void qpdf_set_r4_encryption_parameters(
|
void qpdf_set_r4_encryption_parameters(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
char const* owner_password,
|
||||||
QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
|
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
|
QPDF_DLL
|
||||||
void qpdf_set_r5_encryption_parameters(
|
void qpdf_set_r5_encryption_parameters(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
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 encrypt_metadata);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_set_r6_encryption_parameters(
|
void qpdf_set_r6_encryption_parameters(
|
||||||
qpdf_data qpdf, char const* user_password, char const* owner_password,
|
qpdf_data qpdf,
|
||||||
QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
|
char const* user_password,
|
||||||
enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
|
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 encrypt_metadata);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -648,8 +691,8 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh);
|
qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_replace_object(
|
void
|
||||||
qpdf_data qpdf, int objid, int generation, qpdf_oh oh);
|
qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh);
|
||||||
|
|
||||||
/* Wrappers around QPDFObjectHandle methods. Be sure to read
|
/* Wrappers around QPDFObjectHandle methods. Be sure to read
|
||||||
* corresponding comments in QPDFObjectHandle.hh to understand
|
* corresponding comments in QPDFObjectHandle.hh to understand
|
||||||
@ -690,8 +733,8 @@ extern "C" {
|
|||||||
QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh);
|
QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_is_name_and_equals(
|
QPDF_BOOL
|
||||||
qpdf_data qpdf, qpdf_oh oh, char const* name);
|
qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_is_dictionary_of_type(
|
QPDF_BOOL qpdf_oh_is_dictionary_of_type(
|
||||||
@ -711,19 +754,18 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh);
|
QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_get_value_as_bool(
|
QPDF_BOOL
|
||||||
qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value);
|
qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh);
|
long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_get_value_as_longlong(
|
QPDF_BOOL
|
||||||
qpdf_data qpdf, qpdf_oh oh, long long* value);
|
qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh);
|
int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_get_value_as_int(
|
QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value);
|
||||||
qpdf_data qpdf, qpdf_oh oh, int* value);
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh);
|
unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -732,8 +774,8 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh);
|
unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_get_value_as_uint(
|
QPDF_BOOL
|
||||||
qpdf_data qpdf, qpdf_oh oh, unsigned int* value);
|
qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh);
|
char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh);
|
||||||
@ -746,8 +788,8 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh);
|
double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_get_value_as_number(
|
QPDF_BOOL
|
||||||
qpdf_data qpdf, qpdf_oh oh, double* value);
|
qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh);
|
char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh);
|
||||||
@ -782,11 +824,11 @@ extern "C" {
|
|||||||
QPDF_BOOL qpdf_oh_get_value_as_utf8(
|
QPDF_BOOL qpdf_oh_get_value_as_utf8(
|
||||||
qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
char const* qpdf_oh_get_binary_string_value(
|
char const*
|
||||||
qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
char const* qpdf_oh_get_binary_utf8_value(
|
char const*
|
||||||
qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh);
|
int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh);
|
||||||
@ -822,12 +864,12 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_get_key_if_dict(
|
qpdf_oh
|
||||||
qpdf_data qpdf, qpdf_oh oh, char const* key);
|
qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_BOOL qpdf_oh_is_or_has_name(
|
QPDF_BOOL
|
||||||
qpdf_data qpdf, qpdf_oh oh, char const* key);
|
qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf);
|
qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf);
|
||||||
@ -840,8 +882,8 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value);
|
qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf,
|
qpdf_oh qpdf_oh_new_real_from_double(
|
||||||
double value, int decimal_places);
|
qpdf_data qpdf, double value, int decimal_places);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name);
|
qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -852,9 +894,9 @@ extern "C" {
|
|||||||
* contain atrbitary binary data including embedded null characters.
|
* contain atrbitary binary data including embedded null characters.
|
||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_binary_string(
|
qpdf_oh
|
||||||
qpdf_data qpdf, char const* str, size_t length);
|
qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_binary_unicode_string(
|
qpdf_oh qpdf_oh_new_binary_unicode_string(
|
||||||
qpdf_data qpdf, char const* str, size_t length);
|
qpdf_data qpdf, char const* str, size_t length);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -867,7 +909,7 @@ extern "C" {
|
|||||||
* comments in QPDFObjectHandle.hh for newStream() for additional
|
* comments in QPDFObjectHandle.hh for newStream() for additional
|
||||||
* notes. You must call qpdf_oh_replace_stream_data to provide
|
* notes. You must call qpdf_oh_replace_stream_data to provide
|
||||||
* data for the stream. See STREAM FUNCTIONS below.
|
* data for the stream. See STREAM FUNCTIONS below.
|
||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf);
|
qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf);
|
||||||
|
|
||||||
@ -875,8 +917,8 @@ extern "C" {
|
|||||||
void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh);
|
void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh,
|
void
|
||||||
int at, qpdf_oh item);
|
qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
|
void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
@ -885,13 +927,13 @@ extern "C" {
|
|||||||
void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at);
|
void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh,
|
void qpdf_oh_replace_key(
|
||||||
char const* key, qpdf_oh item);
|
qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh,
|
void qpdf_oh_replace_or_remove_key(
|
||||||
char const* key, qpdf_oh item);
|
qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item);
|
||||||
|
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh);
|
qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh);
|
||||||
@ -946,9 +988,12 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_oh_get_stream_data(
|
QPDF_ERROR_CODE qpdf_oh_get_stream_data(
|
||||||
qpdf_data qpdf, qpdf_oh stream_oh,
|
qpdf_data qpdf,
|
||||||
enum qpdf_stream_decode_level_e decode_level, QPDF_BOOL* filtered,
|
qpdf_oh stream_oh,
|
||||||
unsigned char** bufp, size_t* len);
|
enum qpdf_stream_decode_level_e decode_level,
|
||||||
|
QPDF_BOOL* filtered,
|
||||||
|
unsigned char** bufp,
|
||||||
|
size_t* len);
|
||||||
|
|
||||||
/* This function returns the concatenation of all of a page's
|
/* This function returns the concatenation of all of a page's
|
||||||
* content streams as a single, dynamically allocated buffer. As
|
* content streams as a single, dynamically allocated buffer. As
|
||||||
@ -957,17 +1002,19 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_oh_get_page_content_data(
|
QPDF_ERROR_CODE qpdf_oh_get_page_content_data(
|
||||||
qpdf_data qpdf, qpdf_oh page_oh,
|
qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len);
|
||||||
unsigned char** bufp, size_t* len);
|
|
||||||
|
|
||||||
/* The data pointed to by bufp will be copied by the library. It
|
/* The data pointed to by bufp will be copied by the library. It
|
||||||
* does not need to remain valid after the call returns.
|
* does not need to remain valid after the call returns.
|
||||||
*/
|
*/
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void qpdf_oh_replace_stream_data(
|
void qpdf_oh_replace_stream_data(
|
||||||
qpdf_data qpdf, qpdf_oh stream_oh,
|
qpdf_data qpdf,
|
||||||
unsigned char const* buf, size_t len,
|
qpdf_oh stream_oh,
|
||||||
qpdf_oh filter, qpdf_oh decode_parms);
|
unsigned char const* buf,
|
||||||
|
size_t len,
|
||||||
|
qpdf_oh filter,
|
||||||
|
qpdf_oh decode_parms);
|
||||||
|
|
||||||
/* PAGE FUNCTIONS */
|
/* PAGE FUNCTIONS */
|
||||||
|
|
||||||
@ -1018,14 +1065,17 @@ extern "C" {
|
|||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_add_page(
|
QPDF_ERROR_CODE qpdf_add_page(
|
||||||
qpdf_data qpdf,
|
qpdf_data qpdf,
|
||||||
qpdf_data newpage_qpdf, qpdf_oh newpage,
|
qpdf_data newpage_qpdf,
|
||||||
|
qpdf_oh newpage,
|
||||||
QPDF_BOOL first);
|
QPDF_BOOL first);
|
||||||
/* addPageAt() */
|
/* addPageAt() */
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_add_page_at(
|
QPDF_ERROR_CODE qpdf_add_page_at(
|
||||||
qpdf_data qpdf,
|
qpdf_data qpdf,
|
||||||
qpdf_data newpage_qpdf, qpdf_oh newpage,
|
qpdf_data newpage_qpdf,
|
||||||
QPDF_BOOL before, qpdf_oh refpage);
|
qpdf_oh newpage,
|
||||||
|
QPDF_BOOL before,
|
||||||
|
qpdf_oh refpage);
|
||||||
/* removePage() */
|
/* removePage() */
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page);
|
QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page);
|
||||||
@ -1033,5 +1083,4 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* QPDF_C_H */
|
#endif /* QPDF_C_H */
|
||||||
|
@ -75,5 +75,4 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif /* QPDFJOB_C_H */
|
#endif /* QPDFJOB_C_H */
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
#include <qpdf/AES_PDF_native.hh>
|
#include <qpdf/AES_PDF_native.hh>
|
||||||
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <cstring>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <qpdf/rijndael.h>
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
#include <string>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <qpdf/QPDFCryptoImpl.hh>
|
#include <qpdf/QPDFCryptoImpl.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <qpdf/rijndael.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key,
|
AES_PDF_native::AES_PDF_native(
|
||||||
size_t key_bytes, bool cbc_mode,
|
bool encrypt,
|
||||||
unsigned char* cbc_block) :
|
unsigned char const* key,
|
||||||
|
size_t key_bytes,
|
||||||
|
bool cbc_mode,
|
||||||
|
unsigned char* cbc_block) :
|
||||||
encrypt(encrypt),
|
encrypt(encrypt),
|
||||||
cbc_mode(cbc_mode),
|
cbc_mode(cbc_mode),
|
||||||
cbc_block(cbc_block),
|
cbc_block(cbc_block),
|
||||||
@ -24,15 +27,12 @@ AES_PDF_native::AES_PDF_native(bool encrypt, unsigned char const* key,
|
|||||||
size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
|
size_t rk_bytes = RKLENGTH(keybits) * sizeof(uint32_t);
|
||||||
std::memcpy(this->key.get(), key, key_bytes);
|
std::memcpy(this->key.get(), key, key_bytes);
|
||||||
std::memset(this->rk.get(), 0, rk_bytes);
|
std::memset(this->rk.get(), 0, rk_bytes);
|
||||||
if (encrypt)
|
if (encrypt) {
|
||||||
{
|
this->nrounds =
|
||||||
this->nrounds = rijndaelSetupEncrypt(
|
rijndaelSetupEncrypt(this->rk.get(), this->key.get(), keybits);
|
||||||
this->rk.get(), this->key.get(), keybits);
|
} else {
|
||||||
}
|
this->nrounds =
|
||||||
else
|
rijndaelSetupDecrypt(this->rk.get(), this->key.get(), keybits);
|
||||||
{
|
|
||||||
this->nrounds = rijndaelSetupDecrypt(
|
|
||||||
this->rk.get(), this->key.get(), keybits);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,35 +43,24 @@ AES_PDF_native::~AES_PDF_native()
|
|||||||
void
|
void
|
||||||
AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
|
AES_PDF_native::update(unsigned char* in_data, unsigned char* out_data)
|
||||||
{
|
{
|
||||||
if (this->encrypt)
|
if (this->encrypt) {
|
||||||
{
|
if (this->cbc_mode) {
|
||||||
if (this->cbc_mode)
|
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i) {
|
||||||
{
|
|
||||||
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i)
|
|
||||||
{
|
|
||||||
in_data[i] ^= this->cbc_block[i];
|
in_data[i] ^= this->cbc_block[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rijndaelEncrypt(this->rk.get(),
|
rijndaelEncrypt(this->rk.get(), this->nrounds, in_data, out_data);
|
||||||
this->nrounds, in_data, out_data);
|
if (this->cbc_mode) {
|
||||||
if (this->cbc_mode)
|
memcpy(
|
||||||
{
|
this->cbc_block, out_data, QPDFCryptoImpl::rijndael_buf_size);
|
||||||
memcpy(this->cbc_block, out_data,
|
|
||||||
QPDFCryptoImpl::rijndael_buf_size);
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
rijndaelDecrypt(this->rk.get(), this->nrounds, in_data, out_data);
|
||||||
{
|
if (this->cbc_mode) {
|
||||||
rijndaelDecrypt(this->rk.get(),
|
for (size_t i = 0; i < QPDFCryptoImpl::rijndael_buf_size; ++i) {
|
||||||
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];
|
out_data[i] ^= this->cbc_block[i];
|
||||||
}
|
}
|
||||||
memcpy(this->cbc_block, in_data,
|
memcpy(this->cbc_block, in_data, QPDFCryptoImpl::rijndael_buf_size);
|
||||||
QPDFCryptoImpl::rijndael_buf_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,7 @@ BitStream::reset()
|
|||||||
{
|
{
|
||||||
p = start;
|
p = start;
|
||||||
bit_offset = 7;
|
bit_offset = 7;
|
||||||
if (QIntC::to_uint(nbytes) > static_cast<unsigned int>(-1) / 8)
|
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;
|
bits_available = 8 * nbytes;
|
||||||
@ -28,22 +27,18 @@ BitStream::reset()
|
|||||||
unsigned long long
|
unsigned long long
|
||||||
BitStream::getBits(size_t nbits)
|
BitStream::getBits(size_t nbits)
|
||||||
{
|
{
|
||||||
return read_bits(this->p, this->bit_offset,
|
return read_bits(this->p, this->bit_offset, this->bits_available, nbits);
|
||||||
this->bits_available, nbits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long long
|
long long
|
||||||
BitStream::getBitsSigned(size_t nbits)
|
BitStream::getBitsSigned(size_t nbits)
|
||||||
{
|
{
|
||||||
unsigned long long bits = read_bits(this->p, this->bit_offset,
|
unsigned long long bits =
|
||||||
this->bits_available, nbits);
|
read_bits(this->p, this->bit_offset, this->bits_available, nbits);
|
||||||
long long result = 0;
|
long long result = 0;
|
||||||
if (static_cast<long long>(bits) > 1LL << (nbits - 1))
|
if (static_cast<long long>(bits) > 1LL << (nbits - 1)) {
|
||||||
{
|
result = static_cast<long long>(bits - (1ULL << nbits));
|
||||||
result = static_cast<long long>(bits -(1ULL << nbits));
|
} else {
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = static_cast<long long>(bits);
|
result = static_cast<long long>(bits);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -52,20 +47,16 @@ BitStream::getBitsSigned(size_t nbits)
|
|||||||
int
|
int
|
||||||
BitStream::getBitsInt(size_t nbits)
|
BitStream::getBitsInt(size_t nbits)
|
||||||
{
|
{
|
||||||
return static_cast<int>(
|
return static_cast<int>(QIntC::to_uint(
|
||||||
QIntC::to_uint(
|
read_bits(this->p, this->bit_offset, this->bits_available, nbits)));
|
||||||
read_bits(this->p, this->bit_offset,
|
|
||||||
this->bits_available, nbits)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BitStream::skipToNextByte()
|
BitStream::skipToNextByte()
|
||||||
{
|
{
|
||||||
if (bit_offset != 7)
|
if (bit_offset != 7) {
|
||||||
{
|
|
||||||
size_t bits_to_skip = bit_offset + 1;
|
size_t bits_to_skip = bit_offset + 1;
|
||||||
if (bits_available < bits_to_skip)
|
if (bits_available < bits_to_skip) {
|
||||||
{
|
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"INTERNAL ERROR: overflow skipping to next byte in bitstream");
|
"INTERNAL ERROR: overflow skipping to next byte in bitstream");
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,9 @@ void
|
|||||||
BitWriter::writeBitsSigned(long long val, size_t bits)
|
BitWriter::writeBitsSigned(long long val, size_t bits)
|
||||||
{
|
{
|
||||||
unsigned long long uval = 0;
|
unsigned long long uval = 0;
|
||||||
if (val < 0)
|
if (val < 0) {
|
||||||
{
|
|
||||||
uval = (1ULL << bits) + static_cast<unsigned long long>(val);
|
uval = (1ULL << bits) + static_cast<unsigned long long>(val);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
uval = static_cast<unsigned long long>(val);
|
uval = static_cast<unsigned long long>(val);
|
||||||
}
|
}
|
||||||
writeBits(uval, bits);
|
writeBits(uval, bits);
|
||||||
@ -41,8 +38,7 @@ BitWriter::writeBitsInt(int val, size_t bits)
|
|||||||
void
|
void
|
||||||
BitWriter::flush()
|
BitWriter::flush()
|
||||||
{
|
{
|
||||||
if (bit_offset < 7)
|
if (bit_offset < 7) {
|
||||||
{
|
|
||||||
size_t bits_to_write = bit_offset + 1;
|
size_t bits_to_write = bit_offset + 1;
|
||||||
write_bits(this->ch, this->bit_offset, 0, bits_to_write, this->pl);
|
write_bits(this->ch, this->bit_offset, 0, bits_to_write, this->pl);
|
||||||
}
|
}
|
||||||
|
@ -7,21 +7,17 @@ Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) :
|
|||||||
size(size),
|
size(size),
|
||||||
buf(0)
|
buf(0)
|
||||||
{
|
{
|
||||||
if (own_memory)
|
if (own_memory) {
|
||||||
{
|
|
||||||
this->buf = (size ? new unsigned char[size] : 0);
|
this->buf = (size ? new unsigned char[size] : 0);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
this->buf = buf;
|
this->buf = buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Members::~Members()
|
Buffer::Members::~Members()
|
||||||
{
|
{
|
||||||
if (this->own_memory)
|
if (this->own_memory) {
|
||||||
{
|
delete[] this->buf;
|
||||||
delete [] this->buf;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,11 +51,9 @@ Buffer::operator=(Buffer const& rhs)
|
|||||||
void
|
void
|
||||||
Buffer::copy(Buffer const& rhs)
|
Buffer::copy(Buffer const& rhs)
|
||||||
{
|
{
|
||||||
if (this != &rhs)
|
if (this != &rhs) {
|
||||||
{
|
|
||||||
this->m = PointerHolder<Members>(new Members(rhs.m->size, 0, true));
|
this->m = PointerHolder<Members>(new Members(rhs.m->size, 0, true));
|
||||||
if (this->m->size)
|
if (this->m->size) {
|
||||||
{
|
|
||||||
memcpy(this->m->buf, rhs.m->buf, this->m->size);
|
memcpy(this->m->buf, rhs.m->buf, this->m->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
#include <qpdf/BufferInputSource.hh>
|
#include <qpdf/BufferInputSource.hh>
|
||||||
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
#include <string.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
BufferInputSource::Members::Members(bool own_memory,
|
BufferInputSource::Members::Members(
|
||||||
std::string const& description,
|
bool own_memory, std::string const& description, Buffer* buf) :
|
||||||
Buffer* buf) :
|
|
||||||
own_memory(own_memory),
|
own_memory(own_memory),
|
||||||
description(description),
|
description(description),
|
||||||
buf(buf),
|
buf(buf),
|
||||||
@ -22,14 +21,14 @@ BufferInputSource::Members::~Members()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferInputSource::BufferInputSource(std::string const& description,
|
BufferInputSource::BufferInputSource(
|
||||||
Buffer* buf, bool own_memory) :
|
std::string const& description, Buffer* buf, bool own_memory) :
|
||||||
m(new Members(own_memory, description, buf))
|
m(new Members(own_memory, description, buf))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferInputSource::BufferInputSource(std::string const& description,
|
BufferInputSource::BufferInputSource(
|
||||||
std::string const& contents) :
|
std::string const& description, std::string const& contents) :
|
||||||
m(new Members(true, description, 0))
|
m(new Members(true, description, 0))
|
||||||
{
|
{
|
||||||
this->m->buf = new Buffer(contents.length());
|
this->m->buf = new Buffer(contents.length());
|
||||||
@ -40,8 +39,7 @@ BufferInputSource::BufferInputSource(std::string const& description,
|
|||||||
|
|
||||||
BufferInputSource::~BufferInputSource()
|
BufferInputSource::~BufferInputSource()
|
||||||
{
|
{
|
||||||
if (this->m->own_memory)
|
if (this->m->own_memory) {
|
||||||
{
|
|
||||||
delete this->m->buf;
|
delete this->m->buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,13 +47,11 @@ BufferInputSource::~BufferInputSource()
|
|||||||
qpdf_offset_t
|
qpdf_offset_t
|
||||||
BufferInputSource::findAndSkipNextEOL()
|
BufferInputSource::findAndSkipNextEOL()
|
||||||
{
|
{
|
||||||
if (this->m->cur_offset < 0)
|
if (this->m->cur_offset < 0) {
|
||||||
{
|
|
||||||
throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0");
|
throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0");
|
||||||
}
|
}
|
||||||
qpdf_offset_t end_pos = this->m->max_offset;
|
qpdf_offset_t end_pos = this->m->max_offset;
|
||||||
if (this->m->cur_offset >= end_pos)
|
if (this->m->cur_offset >= end_pos) {
|
||||||
{
|
|
||||||
this->last_offset = end_pos;
|
this->last_offset = end_pos;
|
||||||
this->m->cur_offset = end_pos;
|
this->m->cur_offset = end_pos;
|
||||||
return end_pos;
|
return end_pos;
|
||||||
@ -66,24 +62,19 @@ BufferInputSource::findAndSkipNextEOL()
|
|||||||
unsigned char const* end = buffer + end_pos;
|
unsigned char const* end = buffer + end_pos;
|
||||||
unsigned char const* p = buffer + this->m->cur_offset;
|
unsigned char const* p = buffer + this->m->cur_offset;
|
||||||
|
|
||||||
while ((p < end) && !((*p == '\r') || (*p == '\n')))
|
while ((p < end) && !((*p == '\r') || (*p == '\n'))) {
|
||||||
{
|
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (p < end)
|
if (p < end) {
|
||||||
{
|
|
||||||
result = p - buffer;
|
result = p - buffer;
|
||||||
this->m->cur_offset = result + 1;
|
this->m->cur_offset = result + 1;
|
||||||
++p;
|
++p;
|
||||||
while ((this->m->cur_offset < end_pos) &&
|
while ((this->m->cur_offset < end_pos) &&
|
||||||
((*p == '\r') || (*p == '\n')))
|
((*p == '\r') || (*p == '\n'))) {
|
||||||
{
|
|
||||||
++p;
|
++p;
|
||||||
++this->m->cur_offset;
|
++this->m->cur_offset;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
this->m->cur_offset = end_pos;
|
this->m->cur_offset = end_pos;
|
||||||
result = end_pos;
|
result = end_pos;
|
||||||
}
|
}
|
||||||
@ -105,30 +96,28 @@ BufferInputSource::tell()
|
|||||||
void
|
void
|
||||||
BufferInputSource::seek(qpdf_offset_t offset, int whence)
|
BufferInputSource::seek(qpdf_offset_t offset, int whence)
|
||||||
{
|
{
|
||||||
switch (whence)
|
switch (whence) {
|
||||||
{
|
case SEEK_SET:
|
||||||
case SEEK_SET:
|
|
||||||
this->m->cur_offset = offset;
|
this->m->cur_offset = offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
QIntC::range_check(this->m->max_offset, offset);
|
QIntC::range_check(this->m->max_offset, offset);
|
||||||
this->m->cur_offset = this->m->max_offset + offset;
|
this->m->cur_offset = this->m->max_offset + offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
QIntC::range_check(this->m->cur_offset, offset);
|
QIntC::range_check(this->m->cur_offset, offset);
|
||||||
this->m->cur_offset += offset;
|
this->m->cur_offset += offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"INTERNAL ERROR: invalid argument to BufferInputSource::seek");
|
"INTERNAL ERROR: invalid argument to BufferInputSource::seek");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->m->cur_offset < 0)
|
if (this->m->cur_offset < 0) {
|
||||||
{
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
this->m->description + ": seek before beginning of buffer");
|
this->m->description + ": seek before beginning of buffer");
|
||||||
}
|
}
|
||||||
@ -143,20 +132,18 @@ BufferInputSource::rewind()
|
|||||||
size_t
|
size_t
|
||||||
BufferInputSource::read(char* buffer, size_t length)
|
BufferInputSource::read(char* buffer, size_t length)
|
||||||
{
|
{
|
||||||
if (this->m->cur_offset < 0)
|
if (this->m->cur_offset < 0) {
|
||||||
{
|
|
||||||
throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0");
|
throw std::logic_error("INTERNAL ERROR: BufferInputSource offset < 0");
|
||||||
}
|
}
|
||||||
qpdf_offset_t end_pos = this->m->max_offset;
|
qpdf_offset_t end_pos = this->m->max_offset;
|
||||||
if (this->m->cur_offset >= end_pos)
|
if (this->m->cur_offset >= end_pos) {
|
||||||
{
|
|
||||||
this->last_offset = end_pos;
|
this->last_offset = end_pos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->last_offset = this->m->cur_offset;
|
this->last_offset = this->m->cur_offset;
|
||||||
size_t len = std::min(
|
size_t len =
|
||||||
QIntC::to_size(end_pos - this->m->cur_offset), length);
|
std::min(QIntC::to_size(end_pos - this->m->cur_offset), length);
|
||||||
memcpy(buffer, this->m->buf->getBuffer() + this->m->cur_offset, len);
|
memcpy(buffer, this->m->buf->getBuffer() + this->m->cur_offset, len);
|
||||||
this->m->cur_offset += QIntC::to_offset(len);
|
this->m->cur_offset += QIntC::to_offset(len);
|
||||||
return len;
|
return len;
|
||||||
@ -165,8 +152,7 @@ BufferInputSource::read(char* buffer, size_t length)
|
|||||||
void
|
void
|
||||||
BufferInputSource::unreadCh(char ch)
|
BufferInputSource::unreadCh(char ch)
|
||||||
{
|
{
|
||||||
if (this->m->cur_offset > 0)
|
if (this->m->cur_offset > 0) {
|
||||||
{
|
|
||||||
--this->m->cur_offset;
|
--this->m->cur_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,7 @@ ClosedFileInputSource::~ClosedFileInputSource()
|
|||||||
void
|
void
|
||||||
ClosedFileInputSource::before()
|
ClosedFileInputSource::before()
|
||||||
{
|
{
|
||||||
if (0 == this->m->fis.get())
|
if (0 == this->m->fis.get()) {
|
||||||
{
|
|
||||||
this->m->fis = make_pointer_holder<FileInputSource>();
|
this->m->fis = make_pointer_holder<FileInputSource>();
|
||||||
this->m->fis->setFilename(this->m->filename.c_str());
|
this->m->fis->setFilename(this->m->filename.c_str());
|
||||||
this->m->fis->seek(this->m->offset, SEEK_SET);
|
this->m->fis->seek(this->m->offset, SEEK_SET);
|
||||||
@ -39,8 +38,7 @@ ClosedFileInputSource::after()
|
|||||||
{
|
{
|
||||||
this->last_offset = this->m->fis->getLastOffset();
|
this->last_offset = this->m->fis->getLastOffset();
|
||||||
this->m->offset = this->m->fis->tell();
|
this->m->offset = this->m->fis->tell();
|
||||||
if (this->m->stay_open)
|
if (this->m->stay_open) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->m->fis = 0;
|
this->m->fis = 0;
|
||||||
@ -82,8 +80,7 @@ void
|
|||||||
ClosedFileInputSource::rewind()
|
ClosedFileInputSource::rewind()
|
||||||
{
|
{
|
||||||
this->m->offset = 0;
|
this->m->offset = 0;
|
||||||
if (this->m->fis.get())
|
if (this->m->fis.get()) {
|
||||||
{
|
|
||||||
this->m->fis->rewind();
|
this->m->fis->rewind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,8 +107,7 @@ void
|
|||||||
ClosedFileInputSource::stayOpen(bool val)
|
ClosedFileInputSource::stayOpen(bool val)
|
||||||
{
|
{
|
||||||
this->m->stay_open = val;
|
this->m->stay_open = val;
|
||||||
if ((! val) && this->m->fis.get())
|
if ((!val) && this->m->fis.get()) {
|
||||||
{
|
|
||||||
after();
|
after();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,57 +18,46 @@ ContentNormalizer::handleToken(QPDFTokenizer::Token const& token)
|
|||||||
std::string value = token.getRawValue();
|
std::string value = token.getRawValue();
|
||||||
QPDFTokenizer::token_type_e token_type = token.getType();
|
QPDFTokenizer::token_type_e token_type = token.getType();
|
||||||
|
|
||||||
if (token_type == QPDFTokenizer::tt_bad)
|
if (token_type == QPDFTokenizer::tt_bad) {
|
||||||
{
|
|
||||||
this->any_bad_tokens = true;
|
this->any_bad_tokens = true;
|
||||||
this->last_token_was_bad = true;
|
this->last_token_was_bad = true;
|
||||||
}
|
} else if (token_type != QPDFTokenizer::tt_eof) {
|
||||||
else if (token_type != QPDFTokenizer::tt_eof)
|
|
||||||
{
|
|
||||||
this->last_token_was_bad = false;
|
this->last_token_was_bad = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (token_type)
|
switch (token_type) {
|
||||||
{
|
case QPDFTokenizer::tt_space:
|
||||||
case QPDFTokenizer::tt_space:
|
|
||||||
{
|
{
|
||||||
size_t len = value.length();
|
size_t len = value.length();
|
||||||
for (size_t i = 0; i < len; ++i)
|
for (size_t i = 0; i < len; ++i) {
|
||||||
{
|
|
||||||
char ch = value.at(i);
|
char ch = value.at(i);
|
||||||
if (ch == '\r')
|
if (ch == '\r') {
|
||||||
{
|
if ((i + 1 < len) && (value.at(i + 1) == '\n')) {
|
||||||
if ((i + 1 < len) && (value.at(i + 1) == '\n'))
|
|
||||||
{
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
write("\n");
|
write("\n");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
write(&ch, 1);
|
write(&ch, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QPDFTokenizer::tt_string:
|
case QPDFTokenizer::tt_string:
|
||||||
// Replacing string and name tokens in this way normalizes
|
// Replacing string and name tokens in this way normalizes
|
||||||
// their representation as this will automatically handle
|
// their representation as this will automatically handle
|
||||||
// quoting of unprintable characters, etc.
|
// quoting of unprintable characters, etc.
|
||||||
writeToken(QPDFTokenizer::Token(
|
writeToken(
|
||||||
QPDFTokenizer::tt_string, token.getValue()));
|
QPDFTokenizer::Token(QPDFTokenizer::tt_string, token.getValue()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QPDFTokenizer::tt_name:
|
case QPDFTokenizer::tt_name:
|
||||||
writeToken(QPDFTokenizer::Token(
|
writeToken(
|
||||||
QPDFTokenizer::tt_name, token.getValue()));
|
QPDFTokenizer::Token(QPDFTokenizer::tt_name, token.getValue()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
writeToken(token);
|
writeToken(token);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -77,8 +66,7 @@ ContentNormalizer::handleToken(QPDFTokenizer::Token const& token)
|
|||||||
if (((token_type == QPDFTokenizer::tt_string) ||
|
if (((token_type == QPDFTokenizer::tt_string) ||
|
||||||
(token_type == QPDFTokenizer::tt_name)) &&
|
(token_type == QPDFTokenizer::tt_name)) &&
|
||||||
((value.find('\r') != std::string::npos) ||
|
((value.find('\r') != std::string::npos) ||
|
||||||
(value.find('\n') != std::string::npos)))
|
(value.find('\n') != std::string::npos))) {
|
||||||
{
|
|
||||||
write("\n");
|
write("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -90,7 +78,7 @@ ContentNormalizer::anyBadTokens() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentNormalizer::lastTokenWasBad()const
|
ContentNormalizer::lastTokenWasBad() const
|
||||||
{
|
{
|
||||||
return this->last_token_was_bad;
|
return this->last_token_was_bad;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include <qpdf/FileInputSource.hh>
|
#include <qpdf/FileInputSource.hh>
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QPDFExc.hh>
|
#include <qpdf/QPDFExc.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
FileInputSource::Members::Members(bool close_file) :
|
FileInputSource::Members::Members(bool close_file) :
|
||||||
close_file(close_file),
|
close_file(close_file),
|
||||||
@ -13,8 +13,7 @@ FileInputSource::Members::Members(bool close_file) :
|
|||||||
|
|
||||||
FileInputSource::Members::~Members()
|
FileInputSource::Members::~Members()
|
||||||
{
|
{
|
||||||
if (this->file && this->close_file)
|
if (this->file && this->close_file) {
|
||||||
{
|
|
||||||
fclose(this->file);
|
fclose(this->file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,8 +32,7 @@ FileInputSource::setFilename(char const* filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FileInputSource::setFile(
|
FileInputSource::setFile(char const* description, FILE* filep, bool close_file)
|
||||||
char const* description, FILE* filep, bool close_file)
|
|
||||||
{
|
{
|
||||||
this->m = PointerHolder<Members>(new Members(close_file));
|
this->m = PointerHolder<Members>(new Members(close_file));
|
||||||
this->m->filename = description;
|
this->m->filename = description;
|
||||||
@ -52,35 +50,26 @@ FileInputSource::findAndSkipNextEOL()
|
|||||||
qpdf_offset_t result = 0;
|
qpdf_offset_t result = 0;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
char buf[10240];
|
char buf[10240];
|
||||||
while (! done)
|
while (!done) {
|
||||||
{
|
|
||||||
qpdf_offset_t cur_offset = QUtil::tell(this->m->file);
|
qpdf_offset_t cur_offset = QUtil::tell(this->m->file);
|
||||||
size_t len = this->read(buf, sizeof(buf));
|
size_t len = this->read(buf, sizeof(buf));
|
||||||
if (len == 0)
|
if (len == 0) {
|
||||||
{
|
|
||||||
done = true;
|
done = true;
|
||||||
result = this->tell();
|
result = this->tell();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
char* p1 = static_cast<char*>(memchr(buf, '\r', len));
|
char* p1 = static_cast<char*>(memchr(buf, '\r', len));
|
||||||
char* p2 = static_cast<char*>(memchr(buf, '\n', len));
|
char* p2 = static_cast<char*>(memchr(buf, '\n', len));
|
||||||
char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2;
|
char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2;
|
||||||
if (p)
|
if (p) {
|
||||||
{
|
|
||||||
result = cur_offset + (p - buf);
|
result = cur_offset + (p - buf);
|
||||||
// We found \r or \n. Keep reading until we get past
|
// We found \r or \n. Keep reading until we get past
|
||||||
// \r and \n characters.
|
// \r and \n characters.
|
||||||
this->seek(result + 1, SEEK_SET);
|
this->seek(result + 1, SEEK_SET);
|
||||||
char ch;
|
char ch;
|
||||||
while (! done)
|
while (!done) {
|
||||||
{
|
if (this->read(&ch, 1) == 0) {
|
||||||
if (this->read(&ch, 1) == 0)
|
|
||||||
{
|
|
||||||
done = true;
|
done = true;
|
||||||
}
|
} else if (!((ch == '\r') || (ch == '\n'))) {
|
||||||
else if (! ((ch == '\r') || (ch == '\n')))
|
|
||||||
{
|
|
||||||
this->unreadCh(ch);
|
this->unreadCh(ch);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
@ -106,11 +95,11 @@ FileInputSource::tell()
|
|||||||
void
|
void
|
||||||
FileInputSource::seek(qpdf_offset_t offset, int whence)
|
FileInputSource::seek(qpdf_offset_t offset, int whence)
|
||||||
{
|
{
|
||||||
QUtil::os_wrapper(std::string("seek to ") +
|
QUtil::os_wrapper(
|
||||||
this->m->filename + ", offset " +
|
std::string("seek to ") + this->m->filename + ", offset " +
|
||||||
QUtil::int_to_string(offset) + " (" +
|
QUtil::int_to_string(offset) + " (" + QUtil::int_to_string(whence) +
|
||||||
QUtil::int_to_string(whence) + ")",
|
")",
|
||||||
QUtil::seek(this->m->file, offset, whence));
|
QUtil::seek(this->m->file, offset, whence));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -124,18 +113,16 @@ FileInputSource::read(char* buffer, size_t length)
|
|||||||
{
|
{
|
||||||
this->last_offset = this->tell();
|
this->last_offset = this->tell();
|
||||||
size_t len = fread(buffer, 1, length, this->m->file);
|
size_t len = fread(buffer, 1, length, this->m->file);
|
||||||
if (len == 0)
|
if (len == 0) {
|
||||||
{
|
if (ferror(this->m->file)) {
|
||||||
if (ferror(this->m->file))
|
throw QPDFExc(
|
||||||
{
|
qpdf_e_system,
|
||||||
throw QPDFExc(qpdf_e_system,
|
this->m->filename,
|
||||||
this->m->filename, "",
|
"",
|
||||||
this->last_offset,
|
this->last_offset,
|
||||||
std::string("read ") +
|
std::string("read ") + QUtil::uint_to_string(length) +
|
||||||
QUtil::uint_to_string(length) + " bytes");
|
" bytes");
|
||||||
}
|
} else if (length > 0) {
|
||||||
else if (length > 0)
|
|
||||||
{
|
|
||||||
this->seek(0, SEEK_END);
|
this->seek(0, SEEK_END);
|
||||||
this->last_offset = this->tell();
|
this->last_offset = this->tell();
|
||||||
}
|
}
|
||||||
@ -146,6 +133,7 @@ FileInputSource::read(char* buffer, size_t length)
|
|||||||
void
|
void
|
||||||
FileInputSource::unreadCh(char ch)
|
FileInputSource::unreadCh(char ch)
|
||||||
{
|
{
|
||||||
QUtil::os_wrapper(this->m->filename + ": unread character",
|
QUtil::os_wrapper(
|
||||||
ungetc(static_cast<unsigned char>(ch), this->m->file));
|
this->m->filename + ": unread character",
|
||||||
|
ungetc(static_cast<unsigned char>(ch), this->m->file));
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#include <qpdf/InputSource.hh>
|
#include <qpdf/InputSource.hh>
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <qpdf/QTC.hh>
|
|
||||||
#include <qpdf/PointerHolder.hh>
|
#include <qpdf/PointerHolder.hh>
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
InputSource::Members::Members()
|
InputSource::Members::Members()
|
||||||
{
|
{
|
||||||
@ -45,17 +45,15 @@ InputSource::readLine(size_t max_line_length)
|
|||||||
qpdf_offset_t eol = this->findAndSkipNextEOL();
|
qpdf_offset_t eol = this->findAndSkipNextEOL();
|
||||||
this->last_offset = offset;
|
this->last_offset = offset;
|
||||||
size_t line_length = QIntC::to_size(eol - offset);
|
size_t line_length = QIntC::to_size(eol - offset);
|
||||||
if (line_length < max_line_length)
|
if (line_length < max_line_length) {
|
||||||
{
|
|
||||||
buf[line_length] = '\0';
|
buf[line_length] = '\0';
|
||||||
}
|
}
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
InputSource::findFirst(char const* start_chars,
|
InputSource::findFirst(
|
||||||
qpdf_offset_t offset, size_t len,
|
char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder)
|
||||||
Finder& finder)
|
|
||||||
{
|
{
|
||||||
// Basic approach: search for the first character of start_chars
|
// Basic approach: search for the first character of start_chars
|
||||||
// starting from offset but not going past len (if len != 0). Once
|
// starting from offset but not going past len (if len != 0). Once
|
||||||
@ -74,8 +72,7 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
// To enable us to guarantee null-termination, save an extra byte
|
// To enable us to guarantee null-termination, save an extra byte
|
||||||
// so that buf[size] is valid memory.
|
// so that buf[size] is valid memory.
|
||||||
size_t size = sizeof(buf) - 1;
|
size_t size = sizeof(buf) - 1;
|
||||||
if ((strlen(start_chars) < 1) || (strlen(start_chars) > size))
|
if ((strlen(start_chars) < 1) || (strlen(start_chars) > size)) {
|
||||||
{
|
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"InputSource::findSource called with"
|
"InputSource::findSource called with"
|
||||||
" too small or too large of a character sequence");
|
" too small or too large of a character sequence");
|
||||||
@ -90,8 +87,7 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
// that will cause return on the next pass. Eventually we will
|
// that will cause return on the next pass. Eventually we will
|
||||||
// either be out of range or hit EOF, either of which forces us to
|
// either be out of range or hit EOF, either of which forces us to
|
||||||
// return.
|
// return.
|
||||||
while (true)
|
while (true) {
|
||||||
{
|
|
||||||
// Do we need to read more data? Pretend size = 5, buf starts
|
// Do we need to read more data? Pretend size = 5, buf starts
|
||||||
// at 0, and start_chars has 3 characters. buf[5] is valid and
|
// at 0, and start_chars has 3 characters. buf[5] is valid and
|
||||||
// null. If p == 2, start_chars could be buf[2] through
|
// null. If p == 2, start_chars could be buf[2] through
|
||||||
@ -99,12 +95,12 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
// If p points to buf[size], since strlen(start_chars) is
|
// If p points to buf[size], since strlen(start_chars) is
|
||||||
// always >= 1, this overflow test will be correct for that
|
// always >= 1, this overflow test will be correct for that
|
||||||
// case regardless of start_chars.
|
// case regardless of start_chars.
|
||||||
if ((p == 0) || ((p + strlen(start_chars)) > (buf + bytes_read)))
|
if ((p == 0) || ((p + strlen(start_chars)) > (buf + bytes_read))) {
|
||||||
{
|
if (p) {
|
||||||
if (p)
|
QTC::TC(
|
||||||
{
|
"libtests",
|
||||||
QTC::TC("libtests", "InputSource read next block",
|
"InputSource read next block",
|
||||||
((p == buf + bytes_read) ? 0 : 1));
|
((p == buf + bytes_read) ? 0 : 1));
|
||||||
buf_offset += (p - buf);
|
buf_offset += (p - buf);
|
||||||
}
|
}
|
||||||
this->seek(buf_offset, SEEK_SET);
|
this->seek(buf_offset, SEEK_SET);
|
||||||
@ -113,10 +109,11 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
// we could guarantee null termination as an extra
|
// we could guarantee null termination as an extra
|
||||||
// protection against overrun when using string functions.
|
// protection against overrun when using string functions.
|
||||||
bytes_read = this->read(buf, size);
|
bytes_read = this->read(buf, size);
|
||||||
if (bytes_read < strlen(start_chars))
|
if (bytes_read < strlen(start_chars)) {
|
||||||
{
|
QTC::TC(
|
||||||
QTC::TC("libtests", "InputSource find EOF",
|
"libtests",
|
||||||
bytes_read == 0 ? 0 : 1);
|
"InputSource find EOF",
|
||||||
|
bytes_read == 0 ? 0 : 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memset(buf + bytes_read, '\0', 1 + (size - bytes_read));
|
memset(buf + bytes_read, '\0', 1 + (size - bytes_read));
|
||||||
@ -124,29 +121,24 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search for the first character.
|
// Search for the first character.
|
||||||
if ((p = static_cast<char*>(
|
if ((p = static_cast<char*>(memchr(
|
||||||
memchr(p, start_chars[0],
|
p, start_chars[0], bytes_read - QIntC::to_size(p - buf)))) !=
|
||||||
bytes_read - QIntC::to_size(p - buf)))) != 0)
|
0) {
|
||||||
{
|
if (p == buf) {
|
||||||
if (p == buf)
|
|
||||||
{
|
|
||||||
QTC::TC("libtests", "InputSource found match at buf[0]");
|
QTC::TC("libtests", "InputSource found match at buf[0]");
|
||||||
}
|
}
|
||||||
// Found first letter.
|
// Found first letter.
|
||||||
if (len != 0)
|
if (len != 0) {
|
||||||
{
|
|
||||||
// Make sure it's in range.
|
// Make sure it's in range.
|
||||||
size_t p_relative_offset =
|
size_t p_relative_offset =
|
||||||
QIntC::to_size((p - buf) + (buf_offset - offset));
|
QIntC::to_size((p - buf) + (buf_offset - offset));
|
||||||
if (p_relative_offset >= len)
|
if (p_relative_offset >= len) {
|
||||||
{
|
|
||||||
// out of range
|
// out of range
|
||||||
QTC::TC("libtests", "InputSource out of range");
|
QTC::TC("libtests", "InputSource out of range");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((p + strlen(start_chars)) > (buf + bytes_read))
|
if ((p + strlen(start_chars)) > (buf + bytes_read)) {
|
||||||
{
|
|
||||||
// If there are not enough bytes left in the file for
|
// If there are not enough bytes left in the file for
|
||||||
// start_chars, we will detect this on the next pass
|
// start_chars, we will detect this on the next pass
|
||||||
// as EOF and return.
|
// as EOF and return.
|
||||||
@ -157,30 +149,26 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
// See if p points to a sequence matching start_chars. We
|
// See if p points to a sequence matching start_chars. We
|
||||||
// already checked above to make sure we are not going to
|
// already checked above to make sure we are not going to
|
||||||
// overrun memory.
|
// overrun memory.
|
||||||
if (strncmp(p, start_chars, strlen(start_chars)) == 0)
|
if (strncmp(p, start_chars, strlen(start_chars)) == 0) {
|
||||||
{
|
|
||||||
// Call finder.check() with the input source
|
// Call finder.check() with the input source
|
||||||
// positioned to the point of the match.
|
// positioned to the point of the match.
|
||||||
this->seek(buf_offset + (p - buf), SEEK_SET);
|
this->seek(buf_offset + (p - buf), SEEK_SET);
|
||||||
if (finder.check())
|
if (finder.check()) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
QTC::TC(
|
||||||
|
"libtests",
|
||||||
|
"InputSource start_chars matched but not check");
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
QTC::TC(
|
||||||
QTC::TC("libtests", "InputSource start_chars matched but not check");
|
"libtests",
|
||||||
}
|
"InputSource first char matched but not string");
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("libtests", "InputSource first char matched but not string");
|
|
||||||
}
|
}
|
||||||
// This occurrence of the first character wasn't a match.
|
// This occurrence of the first character wasn't a match.
|
||||||
// Skip over it and keep searching.
|
// Skip over it and keep searching.
|
||||||
++p;
|
++p;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Trigger reading the next block
|
// Trigger reading the next block
|
||||||
p = buf + bytes_read;
|
p = buf + bytes_read;
|
||||||
}
|
}
|
||||||
@ -189,30 +177,24 @@ InputSource::findFirst(char const* start_chars,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
InputSource::findLast(char const* start_chars,
|
InputSource::findLast(
|
||||||
qpdf_offset_t offset, size_t len,
|
char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder)
|
||||||
Finder& finder)
|
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
qpdf_offset_t after_found_offset = 0;
|
qpdf_offset_t after_found_offset = 0;
|
||||||
qpdf_offset_t cur_offset = offset;
|
qpdf_offset_t cur_offset = offset;
|
||||||
size_t cur_len = len;
|
size_t cur_len = len;
|
||||||
while (this->findFirst(start_chars, cur_offset, cur_len, finder))
|
while (this->findFirst(start_chars, cur_offset, cur_len, finder)) {
|
||||||
{
|
if (found) {
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
QTC::TC("libtests", "InputSource findLast found more than one");
|
QTC::TC("libtests", "InputSource findLast found more than one");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
after_found_offset = this->tell();
|
after_found_offset = this->tell();
|
||||||
cur_offset = after_found_offset;
|
cur_offset = after_found_offset;
|
||||||
cur_len = len - QIntC::to_size((cur_offset - offset));
|
cur_len = len - QIntC::to_size((cur_offset - offset));
|
||||||
}
|
}
|
||||||
if (found)
|
if (found) {
|
||||||
{
|
|
||||||
this->seek(after_found_offset, SEEK_SET);
|
this->seek(after_found_offset, SEEK_SET);
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <qpdf/InsecureRandomDataProvider.hh>
|
#include <qpdf/InsecureRandomDataProvider.hh>
|
||||||
|
|
||||||
#include <qpdf/qpdf-config.h>
|
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <qpdf/qpdf-config.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
InsecureRandomDataProvider::InsecureRandomDataProvider() :
|
InsecureRandomDataProvider::InsecureRandomDataProvider() :
|
||||||
@ -16,8 +16,7 @@ InsecureRandomDataProvider::~InsecureRandomDataProvider()
|
|||||||
void
|
void
|
||||||
InsecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len)
|
InsecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < len; ++i)
|
for (size_t i = 0; i < len; ++i) {
|
||||||
{
|
|
||||||
data[i] = static_cast<unsigned char>((this->random() & 0xff0) >> 4);
|
data[i] = static_cast<unsigned char>((this->random() & 0xff0) >> 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,13 +24,12 @@ InsecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len)
|
|||||||
long
|
long
|
||||||
InsecureRandomDataProvider::random()
|
InsecureRandomDataProvider::random()
|
||||||
{
|
{
|
||||||
if (! this->seeded_random)
|
if (!this->seeded_random) {
|
||||||
{
|
|
||||||
// Seed the random number generator with something simple, but
|
// Seed the random number generator with something simple, but
|
||||||
// just to be interesting, don't use the unmodified current
|
// just to be interesting, don't use the unmodified current
|
||||||
// time. It would be better if this were a more secure seed.
|
// time. It would be better if this were a more secure seed.
|
||||||
unsigned int seed = static_cast<unsigned int>(
|
unsigned int seed =
|
||||||
QUtil::get_current_time() ^ 0xcccc);
|
static_cast<unsigned int>(QUtil::get_current_time() ^ 0xcccc);
|
||||||
#ifdef HAVE_RANDOM
|
#ifdef HAVE_RANDOM
|
||||||
::srandom(seed);
|
::srandom(seed);
|
||||||
#else
|
#else
|
||||||
@ -40,11 +38,11 @@ InsecureRandomDataProvider::random()
|
|||||||
this->seeded_random = true;
|
this->seeded_random = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifdef HAVE_RANDOM
|
#ifdef HAVE_RANDOM
|
||||||
return ::random();
|
return ::random();
|
||||||
# else
|
#else
|
||||||
return rand();
|
return rand();
|
||||||
# endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RandomDataProvider*
|
RandomDataProvider*
|
||||||
|
708
libqpdf/JSON.cc
708
libqpdf/JSON.cc
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
#include <qpdf/JSONHandler.hh>
|
#include <qpdf/JSONHandler.hh>
|
||||||
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QTC.hh>
|
|
||||||
#include <qpdf/QPDFUsage.hh>
|
#include <qpdf/QPDFUsage.hh>
|
||||||
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
JSONHandler::JSONHandler() :
|
JSONHandler::JSONHandler() :
|
||||||
m(new Members())
|
m(new Members())
|
||||||
@ -70,9 +70,10 @@ JSONHandler::addFallbackDictHandler(std::shared_ptr<JSONHandler> fdh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JSONHandler::addArrayHandlers(json_handler_t start_fn,
|
JSONHandler::addArrayHandlers(
|
||||||
void_handler_t end_fn,
|
json_handler_t start_fn,
|
||||||
std::shared_ptr<JSONHandler> ah)
|
void_handler_t end_fn,
|
||||||
|
std::shared_ptr<JSONHandler> ah)
|
||||||
{
|
{
|
||||||
this->m->h.array_start_handler = start_fn;
|
this->m->h.array_start_handler = start_fn;
|
||||||
this->m->h.array_end_handler = end_fn;
|
this->m->h.array_end_handler = end_fn;
|
||||||
@ -82,69 +83,55 @@ JSONHandler::addArrayHandlers(json_handler_t start_fn,
|
|||||||
void
|
void
|
||||||
JSONHandler::handle(std::string const& path, JSON j)
|
JSONHandler::handle(std::string const& path, JSON j)
|
||||||
{
|
{
|
||||||
if (this->m->h.any_handler)
|
if (this->m->h.any_handler) {
|
||||||
{
|
|
||||||
this->m->h.any_handler(path, j);
|
this->m->h.any_handler(path, j);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
bool bvalue = false;
|
bool bvalue = false;
|
||||||
std::string s_value;
|
std::string s_value;
|
||||||
if (this->m->h.null_handler && j.isNull())
|
if (this->m->h.null_handler && j.isNull()) {
|
||||||
{
|
|
||||||
this->m->h.null_handler(path);
|
this->m->h.null_handler(path);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
if (this->m->h.string_handler && j.getString(s_value))
|
if (this->m->h.string_handler && j.getString(s_value)) {
|
||||||
{
|
|
||||||
this->m->h.string_handler(path, s_value);
|
this->m->h.string_handler(path, s_value);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
if (this->m->h.number_handler && j.getNumber(s_value))
|
if (this->m->h.number_handler && j.getNumber(s_value)) {
|
||||||
{
|
|
||||||
this->m->h.number_handler(path, s_value);
|
this->m->h.number_handler(path, s_value);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
if (this->m->h.bool_handler && j.getBool(bvalue))
|
if (this->m->h.bool_handler && j.getBool(bvalue)) {
|
||||||
{
|
|
||||||
this->m->h.bool_handler(path, bvalue);
|
this->m->h.bool_handler(path, bvalue);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
if (this->m->h.dict_start_handler && j.isDictionary())
|
if (this->m->h.dict_start_handler && j.isDictionary()) {
|
||||||
{
|
|
||||||
this->m->h.dict_start_handler(path, j);
|
this->m->h.dict_start_handler(path, j);
|
||||||
std::string path_base = path;
|
std::string path_base = path;
|
||||||
if (path_base != ".")
|
if (path_base != ".") {
|
||||||
{
|
|
||||||
path_base += ".";
|
path_base += ".";
|
||||||
}
|
}
|
||||||
j.forEachDictItem([&path, &path_base, this](
|
j.forEachDictItem([&path, &path_base, this](
|
||||||
std::string const& k, JSON v) {
|
std::string const& k, JSON v) {
|
||||||
auto i = this->m->h.dict_handlers.find(k);
|
auto i = this->m->h.dict_handlers.find(k);
|
||||||
if (i == this->m->h.dict_handlers.end())
|
if (i == this->m->h.dict_handlers.end()) {
|
||||||
{
|
if (this->m->h.fallback_dict_handler.get()) {
|
||||||
if (this->m->h.fallback_dict_handler.get())
|
this->m->h.fallback_dict_handler->handle(path_base + k, v);
|
||||||
{
|
} else {
|
||||||
this->m->h.fallback_dict_handler->handle(
|
|
||||||
path_base + k, v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("libtests", "JSONHandler unexpected key");
|
QTC::TC("libtests", "JSONHandler unexpected key");
|
||||||
usage("JSON handler found unexpected key " + k +
|
usage(
|
||||||
" in object at " + path);
|
"JSON handler found unexpected key " + k +
|
||||||
|
" in object at " + path);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
i->second->handle(path_base + k, v);
|
i->second->handle(path_base + k, v);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this->m->h.dict_end_handler(path);
|
this->m->h.dict_end_handler(path);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
if (this->m->h.array_start_handler && j.isArray())
|
if (this->m->h.array_start_handler && j.isArray()) {
|
||||||
{
|
|
||||||
this->m->h.array_start_handler(path, j);
|
this->m->h.array_start_handler(path, j);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
j.forEachArrayItem([&i, &path, this](JSON v) {
|
j.forEachArrayItem([&i, &path, this](JSON v) {
|
||||||
@ -156,8 +143,7 @@ JSONHandler::handle(std::string const& path, JSON j)
|
|||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! handled)
|
if (!handled) {
|
||||||
{
|
|
||||||
// It would be nice to include information about what type the
|
// It would be nice to include information about what type the
|
||||||
// object was and what types were allowed, but we're relying
|
// object was and what types were allowed, but we're relying
|
||||||
// on schema validation to make sure input is properly
|
// on schema validation to make sure input is properly
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#include <qpdf/MD5.hh>
|
#include <qpdf/MD5.hh>
|
||||||
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDFCryptoProvider.hh>
|
#include <qpdf/QPDFCryptoProvider.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <errno.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
MD5::MD5()
|
MD5::MD5()
|
||||||
{
|
{
|
||||||
@ -28,12 +28,14 @@ MD5::finalize()
|
|||||||
this->crypto->MD5_finalize();
|
this->crypto->MD5_finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::reset()
|
void
|
||||||
|
MD5::reset()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::encodeString(char const* str)
|
void
|
||||||
|
MD5::encodeString(char const* str)
|
||||||
{
|
{
|
||||||
size_t len = strlen(str);
|
size_t len = strlen(str);
|
||||||
crypto->MD5_init();
|
crypto->MD5_init();
|
||||||
@ -41,79 +43,78 @@ void MD5::encodeString(char const* str)
|
|||||||
crypto->MD5_finalize();
|
crypto->MD5_finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::appendString(char const* input_string)
|
void
|
||||||
|
MD5::appendString(char const* input_string)
|
||||||
{
|
{
|
||||||
encodeDataIncrementally(input_string, strlen(input_string));
|
encodeDataIncrementally(input_string, strlen(input_string));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::encodeDataIncrementally(char const* data, size_t len)
|
void
|
||||||
|
MD5::encodeDataIncrementally(char const* data, size_t len)
|
||||||
{
|
{
|
||||||
this->crypto->MD5_update(QUtil::unsigned_char_pointer(data), len);
|
this->crypto->MD5_update(QUtil::unsigned_char_pointer(data), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::encodeFile(char const *filename, qpdf_offset_t up_to_offset)
|
void
|
||||||
|
MD5::encodeFile(char const* filename, qpdf_offset_t up_to_offset)
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
|
|
||||||
FILE *file = QUtil::safe_fopen(filename, "rb");
|
FILE* file = QUtil::safe_fopen(filename, "rb");
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t so_far = 0;
|
size_t so_far = 0;
|
||||||
size_t to_try = 1024;
|
size_t to_try = 1024;
|
||||||
size_t up_to_size = 0;
|
size_t up_to_size = 0;
|
||||||
if (up_to_offset >= 0)
|
if (up_to_offset >= 0) {
|
||||||
{
|
|
||||||
up_to_size = QIntC::to_size(up_to_offset);
|
up_to_size = QIntC::to_size(up_to_offset);
|
||||||
}
|
}
|
||||||
do
|
do {
|
||||||
{
|
if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size)) {
|
||||||
if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size))
|
|
||||||
{
|
|
||||||
to_try = up_to_size - so_far;
|
to_try = up_to_size - so_far;
|
||||||
}
|
}
|
||||||
len = fread(buffer, 1, to_try, file);
|
len = fread(buffer, 1, to_try, file);
|
||||||
if (len > 0)
|
if (len > 0) {
|
||||||
{
|
|
||||||
encodeDataIncrementally(buffer, len);
|
encodeDataIncrementally(buffer, len);
|
||||||
so_far += len;
|
so_far += len;
|
||||||
if ((up_to_offset >= 0) && (so_far >= up_to_size))
|
if ((up_to_offset >= 0) && (so_far >= up_to_size)) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
if (ferror(file))
|
if (ferror(file)) {
|
||||||
{
|
|
||||||
// Assume, perhaps incorrectly, that errno was set by the
|
// Assume, perhaps incorrectly, that errno was set by the
|
||||||
// underlying call to read....
|
// underlying call to read....
|
||||||
(void) fclose(file);
|
(void)fclose(file);
|
||||||
QUtil::throw_system_error(
|
QUtil::throw_system_error(
|
||||||
std::string("MD5: read error on ") + filename);
|
std::string("MD5: read error on ") + filename);
|
||||||
}
|
}
|
||||||
(void) fclose(file);
|
(void)fclose(file);
|
||||||
|
|
||||||
this->crypto->MD5_finalize();
|
this->crypto->MD5_finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::digest(Digest result)
|
void
|
||||||
|
MD5::digest(Digest result)
|
||||||
{
|
{
|
||||||
this->crypto->MD5_finalize();
|
this->crypto->MD5_finalize();
|
||||||
this->crypto->MD5_digest(result);
|
this->crypto->MD5_digest(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MD5::print()
|
void
|
||||||
|
MD5::print()
|
||||||
{
|
{
|
||||||
Digest digest_val;
|
Digest digest_val;
|
||||||
digest(digest_val);
|
digest(digest_val);
|
||||||
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i) {
|
||||||
{
|
|
||||||
printf("%02x", digest_val[i]);
|
printf("%02x", digest_val[i]);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MD5::unparse()
|
std::string
|
||||||
|
MD5::unparse()
|
||||||
{
|
{
|
||||||
this->crypto->MD5_finalize();
|
this->crypto->MD5_finalize();
|
||||||
Digest digest_val;
|
Digest digest_val;
|
||||||
@ -139,25 +140,23 @@ MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MD5::checkDataChecksum(char const* const checksum,
|
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);
|
std::string actual_checksum = getDataChecksum(buf, len);
|
||||||
return (checksum == actual_checksum);
|
return (checksum == actual_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MD5::checkFileChecksum(char const* const checksum,
|
MD5::checkFileChecksum(
|
||||||
char const* filename, qpdf_offset_t up_to_offset)
|
char const* const checksum,
|
||||||
|
char const* filename,
|
||||||
|
qpdf_offset_t up_to_offset)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
std::string actual_checksum = getFileChecksum(filename, up_to_offset);
|
std::string actual_checksum = getFileChecksum(filename, up_to_offset);
|
||||||
result = (checksum == actual_checksum);
|
result = (checksum == actual_checksum);
|
||||||
}
|
} catch (std::runtime_error const&) {
|
||||||
catch (std::runtime_error const&)
|
|
||||||
{
|
|
||||||
// Ignore -- return false
|
// Ignore -- return false
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,13 +4,12 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
OffsetInputSource::OffsetInputSource(PointerHolder<InputSource> proxied,
|
OffsetInputSource::OffsetInputSource(
|
||||||
qpdf_offset_t global_offset) :
|
PointerHolder<InputSource> proxied, qpdf_offset_t global_offset) :
|
||||||
proxied(proxied),
|
proxied(proxied),
|
||||||
global_offset(global_offset)
|
global_offset(global_offset)
|
||||||
{
|
{
|
||||||
if (global_offset < 0)
|
if (global_offset < 0) {
|
||||||
{
|
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"OffsetInputSource constructed with negative offset");
|
"OffsetInputSource constructed with negative offset");
|
||||||
}
|
}
|
||||||
@ -43,25 +42,19 @@ OffsetInputSource::tell()
|
|||||||
void
|
void
|
||||||
OffsetInputSource::seek(qpdf_offset_t offset, int whence)
|
OffsetInputSource::seek(qpdf_offset_t offset, int whence)
|
||||||
{
|
{
|
||||||
if (whence == SEEK_SET)
|
if (whence == SEEK_SET) {
|
||||||
{
|
if (offset > this->max_safe_offset) {
|
||||||
if (offset > this->max_safe_offset)
|
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
std::ostringstream msg;
|
||||||
msg.imbue(std::locale::classic());
|
msg.imbue(std::locale::classic());
|
||||||
msg << "seeking to " << offset
|
msg << "seeking to " << offset << " offset by " << global_offset
|
||||||
<< " offset by " << global_offset
|
|
||||||
<< " would cause an overflow of the offset type";
|
<< " would cause an overflow of the offset type";
|
||||||
throw std::range_error(msg.str());
|
throw std::range_error(msg.str());
|
||||||
}
|
}
|
||||||
this->proxied->seek(offset + global_offset, whence);
|
this->proxied->seek(offset + global_offset, whence);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
this->proxied->seek(offset, whence);
|
this->proxied->seek(offset, whence);
|
||||||
}
|
}
|
||||||
if (tell() < 0)
|
if (tell() < 0) {
|
||||||
{
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"offset input source: seek before beginning of file");
|
"offset input source: seek before beginning of file");
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ PDFVersion::PDFVersion() :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFVersion::PDFVersion(int major_version, int minor_version, int extension_level) :
|
PDFVersion::PDFVersion(
|
||||||
|
int major_version, int minor_version, int extension_level) :
|
||||||
major_version(major_version),
|
major_version(major_version),
|
||||||
minor_version(minor_version),
|
minor_version(minor_version),
|
||||||
extension_level(extension_level)
|
extension_level(extension_level)
|
||||||
@ -17,27 +18,28 @@ PDFVersion::PDFVersion(int major_version, int minor_version, int extension_level
|
|||||||
bool
|
bool
|
||||||
PDFVersion::operator<(PDFVersion const& rhs) const
|
PDFVersion::operator<(PDFVersion const& rhs) const
|
||||||
{
|
{
|
||||||
return ((this->major_version < rhs.major_version) ? true :
|
return (
|
||||||
(this->major_version > rhs.major_version) ? false :
|
(this->major_version < rhs.major_version) ? true
|
||||||
(this->minor_version < rhs.minor_version) ? true :
|
: (this->major_version > rhs.major_version) ? false
|
||||||
(this->minor_version > rhs.minor_version) ? false :
|
: (this->minor_version < rhs.minor_version) ? true
|
||||||
(this->extension_level < rhs.extension_level) ? true :
|
: (this->minor_version > rhs.minor_version) ? false
|
||||||
false);
|
: (this->extension_level < rhs.extension_level) ? true
|
||||||
|
: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PDFVersion::operator==(PDFVersion const& rhs) const
|
PDFVersion::operator==(PDFVersion const& rhs) const
|
||||||
{
|
{
|
||||||
return ((this->major_version == rhs.major_version) &&
|
return (
|
||||||
(this->minor_version == rhs.minor_version) &&
|
(this->major_version == rhs.major_version) &&
|
||||||
(this->extension_level == rhs.extension_level));
|
(this->minor_version == rhs.minor_version) &&
|
||||||
|
(this->extension_level == rhs.extension_level));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PDFVersion::updateIfGreater(PDFVersion const& other)
|
PDFVersion::updateIfGreater(PDFVersion const& other)
|
||||||
{
|
{
|
||||||
if (*this < other)
|
if (*this < other) {
|
||||||
{
|
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,7 @@ Pipeline::~Pipeline()
|
|||||||
Pipeline*
|
Pipeline*
|
||||||
Pipeline::getNext(bool allow_null)
|
Pipeline::getNext(bool allow_null)
|
||||||
{
|
{
|
||||||
if ((this->next == 0) && (! allow_null))
|
if ((this->next == 0) && (!allow_null)) {
|
||||||
{
|
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
this->identifier +
|
this->identifier +
|
||||||
": Pipeline::getNext() called on pipeline with no next");
|
": Pipeline::getNext() called on pipeline with no next");
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
#include <qpdf/Pl_AES_PDF.hh>
|
#include <qpdf/Pl_AES_PDF.hh>
|
||||||
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <cstring>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
#include <qpdf/QPDFCryptoProvider.hh>
|
#include <qpdf/QPDFCryptoProvider.hh>
|
||||||
#include <string>
|
#include <qpdf/QUtil.hh>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
bool Pl_AES_PDF::use_static_iv = false;
|
bool Pl_AES_PDF::use_static_iv = false;
|
||||||
|
|
||||||
Pl_AES_PDF::Pl_AES_PDF(char const* identifier, Pipeline* next,
|
Pl_AES_PDF::Pl_AES_PDF(
|
||||||
bool encrypt, unsigned char const* key,
|
char const* identifier,
|
||||||
size_t key_bytes) :
|
Pipeline* next,
|
||||||
|
bool encrypt,
|
||||||
|
unsigned char const* key,
|
||||||
|
size_t key_bytes) :
|
||||||
Pipeline(identifier, next),
|
Pipeline(identifier, next),
|
||||||
crypto(QPDFCryptoProvider::getImpl()),
|
crypto(QPDFCryptoProvider::getImpl()),
|
||||||
encrypt(encrypt),
|
encrypt(encrypt),
|
||||||
@ -51,11 +54,11 @@ Pl_AES_PDF::disablePadding()
|
|||||||
void
|
void
|
||||||
Pl_AES_PDF::setIV(unsigned char const* iv, size_t bytes)
|
Pl_AES_PDF::setIV(unsigned char const* iv, size_t bytes)
|
||||||
{
|
{
|
||||||
if (bytes != this->buf_size)
|
if (bytes != this->buf_size) {
|
||||||
{
|
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"Pl_AES_PDF: specified initialization vector"
|
"Pl_AES_PDF: specified initialization vector"
|
||||||
" size in bytes must be " + QUtil::uint_to_string(bytes));
|
" size in bytes must be " +
|
||||||
|
QUtil::uint_to_string(bytes));
|
||||||
}
|
}
|
||||||
this->use_specified_iv = true;
|
this->use_specified_iv = true;
|
||||||
memcpy(this->specified_iv, iv, bytes);
|
memcpy(this->specified_iv, iv, bytes);
|
||||||
@ -79,10 +82,8 @@ Pl_AES_PDF::write(unsigned char* data, size_t len)
|
|||||||
size_t bytes_left = len;
|
size_t bytes_left = len;
|
||||||
unsigned char* p = data;
|
unsigned char* p = data;
|
||||||
|
|
||||||
while (bytes_left > 0)
|
while (bytes_left > 0) {
|
||||||
{
|
if (this->offset == this->buf_size) {
|
||||||
if (this->offset == this->buf_size)
|
|
||||||
{
|
|
||||||
flush(false);
|
flush(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,39 +99,32 @@ Pl_AES_PDF::write(unsigned char* data, size_t len)
|
|||||||
void
|
void
|
||||||
Pl_AES_PDF::finish()
|
Pl_AES_PDF::finish()
|
||||||
{
|
{
|
||||||
if (this->encrypt)
|
if (this->encrypt) {
|
||||||
{
|
if (this->offset == this->buf_size) {
|
||||||
if (this->offset == this->buf_size)
|
|
||||||
{
|
|
||||||
flush(false);
|
flush(false);
|
||||||
}
|
}
|
||||||
if (! this->disable_padding)
|
if (!this->disable_padding) {
|
||||||
{
|
|
||||||
// Pad as described in section 3.5.1 of version 1.7 of the PDF
|
// Pad as described in section 3.5.1 of version 1.7 of the PDF
|
||||||
// specification, including providing an entire block of padding
|
// specification, including providing an entire block of padding
|
||||||
// if the input was a multiple of 16 bytes.
|
// if the input was a multiple of 16 bytes.
|
||||||
unsigned char pad =
|
unsigned char pad = QIntC::to_uchar(this->buf_size - this->offset);
|
||||||
QIntC::to_uchar(this->buf_size - this->offset);
|
|
||||||
memset(this->inbuf + this->offset, pad, pad);
|
memset(this->inbuf + this->offset, pad, pad);
|
||||||
this->offset = this->buf_size;
|
this->offset = this->buf_size;
|
||||||
flush(false);
|
flush(false);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
if (this->offset != this->buf_size) {
|
||||||
{
|
|
||||||
if (this->offset != this->buf_size)
|
|
||||||
{
|
|
||||||
// This is never supposed to happen as the output is
|
// This is never supposed to happen as the output is
|
||||||
// always supposed to be padded. However, we have
|
// always supposed to be padded. However, we have
|
||||||
// encountered files for which the output is not a
|
// encountered files for which the output is not a
|
||||||
// multiple of the block size. In this case, pad with
|
// multiple of the block size. In this case, pad with
|
||||||
// zeroes and hope for the best.
|
// zeroes and hope for the best.
|
||||||
assert(this->buf_size > this->offset);
|
assert(this->buf_size > this->offset);
|
||||||
std::memset(this->inbuf + this->offset, 0,
|
std::memset(
|
||||||
this->buf_size - this->offset);
|
this->inbuf + this->offset, 0, this->buf_size - this->offset);
|
||||||
this->offset = this->buf_size;
|
this->offset = this->buf_size;
|
||||||
}
|
}
|
||||||
flush(! this->disable_padding);
|
flush(!this->disable_padding);
|
||||||
}
|
}
|
||||||
this->crypto->rijndael_finalize();
|
this->crypto->rijndael_finalize();
|
||||||
getNext()->finish();
|
getNext()->finish();
|
||||||
@ -139,26 +133,17 @@ Pl_AES_PDF::finish()
|
|||||||
void
|
void
|
||||||
Pl_AES_PDF::initializeVector()
|
Pl_AES_PDF::initializeVector()
|
||||||
{
|
{
|
||||||
if (use_zero_iv)
|
if (use_zero_iv) {
|
||||||
{
|
for (unsigned int i = 0; i < this->buf_size; ++i) {
|
||||||
for (unsigned int i = 0; i < this->buf_size; ++i)
|
|
||||||
{
|
|
||||||
this->cbc_block[i] = 0;
|
this->cbc_block[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
} else if (use_specified_iv) {
|
||||||
else if (use_specified_iv)
|
|
||||||
{
|
|
||||||
std::memcpy(this->cbc_block, this->specified_iv, this->buf_size);
|
std::memcpy(this->cbc_block, this->specified_iv, this->buf_size);
|
||||||
}
|
} else if (use_static_iv) {
|
||||||
else if (use_static_iv)
|
for (unsigned int i = 0; i < this->buf_size; ++i) {
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < this->buf_size; ++i)
|
|
||||||
{
|
|
||||||
this->cbc_block[i] = static_cast<unsigned char>(14U * (1U + i));
|
this->cbc_block[i] = static_cast<unsigned char>(14U * (1U + i));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QUtil::initializeWithRandomBytes(this->cbc_block, this->buf_size);
|
QUtil::initializeWithRandomBytes(this->cbc_block, this->buf_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,30 +153,22 @@ Pl_AES_PDF::flush(bool strip_padding)
|
|||||||
{
|
{
|
||||||
assert(this->offset == this->buf_size);
|
assert(this->offset == this->buf_size);
|
||||||
|
|
||||||
if (first)
|
if (first) {
|
||||||
{
|
|
||||||
first = false;
|
first = false;
|
||||||
bool return_after_init = false;
|
bool return_after_init = false;
|
||||||
if (this->cbc_mode)
|
if (this->cbc_mode) {
|
||||||
{
|
if (encrypt) {
|
||||||
if (encrypt)
|
|
||||||
{
|
|
||||||
// Set cbc_block to the initialization vector, and if
|
// Set cbc_block to the initialization vector, and if
|
||||||
// not zero, write it to the output stream.
|
// not zero, write it to the output stream.
|
||||||
initializeVector();
|
initializeVector();
|
||||||
if (! (this->use_zero_iv || this->use_specified_iv))
|
if (!(this->use_zero_iv || this->use_specified_iv)) {
|
||||||
{
|
|
||||||
getNext()->write(this->cbc_block, this->buf_size);
|
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
|
// Initialize vector with zeroes; zero vector was not
|
||||||
// written to the beginning of the input file.
|
// written to the beginning of the input file.
|
||||||
initializeVector();
|
initializeVector();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Take the first block of input as the initialization
|
// Take the first block of input as the initialization
|
||||||
// vector. There's nothing to write at this time.
|
// vector. There's nothing to write at this time.
|
||||||
memcpy(this->cbc_block, this->inbuf, this->buf_size);
|
memcpy(this->cbc_block, this->inbuf, this->buf_size);
|
||||||
@ -200,32 +177,29 @@ Pl_AES_PDF::flush(bool strip_padding)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->crypto->rijndael_init(
|
this->crypto->rijndael_init(
|
||||||
encrypt, this->key.get(), key_bytes,
|
encrypt,
|
||||||
this->cbc_mode, this->cbc_block);
|
this->key.get(),
|
||||||
if (return_after_init)
|
key_bytes,
|
||||||
{
|
this->cbc_mode,
|
||||||
|
this->cbc_block);
|
||||||
|
if (return_after_init) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->crypto->rijndael_process(this->inbuf, this->outbuf);
|
this->crypto->rijndael_process(this->inbuf, this->outbuf);
|
||||||
unsigned int bytes = this->buf_size;
|
unsigned int bytes = this->buf_size;
|
||||||
if (strip_padding)
|
if (strip_padding) {
|
||||||
{
|
|
||||||
unsigned char last = this->outbuf[this->buf_size - 1];
|
unsigned char last = this->outbuf[this->buf_size - 1];
|
||||||
if (last <= this->buf_size)
|
if (last <= this->buf_size) {
|
||||||
{
|
|
||||||
bool strip = true;
|
bool strip = true;
|
||||||
for (unsigned int i = 1; i <= last; ++i)
|
for (unsigned int i = 1; i <= last; ++i) {
|
||||||
{
|
if (this->outbuf[this->buf_size - i] != last) {
|
||||||
if (this->outbuf[this->buf_size - i] != last)
|
|
||||||
{
|
|
||||||
strip = false;
|
strip = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (strip)
|
if (strip) {
|
||||||
{
|
|
||||||
bytes -= last;
|
bytes -= last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,55 +19,41 @@ Pl_ASCII85Decoder::~Pl_ASCII85Decoder()
|
|||||||
void
|
void
|
||||||
Pl_ASCII85Decoder::write(unsigned char* buf, size_t len)
|
Pl_ASCII85Decoder::write(unsigned char* buf, size_t len)
|
||||||
{
|
{
|
||||||
if (eod > 1)
|
if (eod > 1) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < len; ++i)
|
for (size_t i = 0; i < len; ++i) {
|
||||||
{
|
if (eod > 1) {
|
||||||
if (eod > 1)
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
} else if (eod == 1) {
|
||||||
else if (eod == 1)
|
if (buf[i] == '>') {
|
||||||
{
|
|
||||||
if (buf[i] == '>')
|
|
||||||
{
|
|
||||||
flush();
|
flush();
|
||||||
eod = 2;
|
eod = 2;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"broken end-of-data sequence in base 85 data");
|
"broken end-of-data sequence in base 85 data");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
switch (buf[i]) {
|
||||||
{
|
case ' ':
|
||||||
switch (buf[i])
|
case '\f':
|
||||||
{
|
case '\v':
|
||||||
case ' ':
|
case '\t':
|
||||||
case '\f':
|
case '\r':
|
||||||
case '\v':
|
case '\n':
|
||||||
case '\t':
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
QTC::TC("libtests", "Pl_ASCII85Decoder ignore space");
|
QTC::TC("libtests", "Pl_ASCII85Decoder ignore space");
|
||||||
// ignore whitespace
|
// ignore whitespace
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '~':
|
case '~':
|
||||||
eod = 1;
|
eod = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'z':
|
case 'z':
|
||||||
if (pos != 0)
|
if (pos != 0) {
|
||||||
{
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"unexpected z during base 85 decode");
|
"unexpected z during base 85 decode");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
|
QTC::TC("libtests", "Pl_ASCII85Decoder read z");
|
||||||
unsigned char zeroes[4];
|
unsigned char zeroes[4];
|
||||||
memset(zeroes, '\0', 4);
|
memset(zeroes, '\0', 4);
|
||||||
@ -75,17 +61,13 @@ Pl_ASCII85Decoder::write(unsigned char* buf, size_t len)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((buf[i] < 33) || (buf[i] > 117))
|
if ((buf[i] < 33) || (buf[i] > 117)) {
|
||||||
{
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"character out of range during base 85 decode");
|
"character out of range during base 85 decode");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
this->inbuf[this->pos++] = buf[i];
|
this->inbuf[this->pos++] = buf[i];
|
||||||
if (pos == 5)
|
if (pos == 5) {
|
||||||
{
|
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,28 +80,27 @@ Pl_ASCII85Decoder::write(unsigned char* buf, size_t len)
|
|||||||
void
|
void
|
||||||
Pl_ASCII85Decoder::flush()
|
Pl_ASCII85Decoder::flush()
|
||||||
{
|
{
|
||||||
if (this->pos == 0)
|
if (this->pos == 0) {
|
||||||
{
|
|
||||||
QTC::TC("libtests", "Pl_ASCII85Decoder no-op flush");
|
QTC::TC("libtests", "Pl_ASCII85Decoder no-op flush");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsigned long lval = 0;
|
unsigned long lval = 0;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i) {
|
||||||
{
|
|
||||||
lval *= 85;
|
lval *= 85;
|
||||||
lval += (this->inbuf[i] - 33U);
|
lval += (this->inbuf[i] - 33U);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char outbuf[4];
|
unsigned char outbuf[4];
|
||||||
memset(outbuf, 0, 4);
|
memset(outbuf, 0, 4);
|
||||||
for (int i = 3; i >= 0; --i)
|
for (int i = 3; i >= 0; --i) {
|
||||||
{
|
|
||||||
outbuf[i] = lval & 0xff;
|
outbuf[i] = lval & 0xff;
|
||||||
lval >>= 8;
|
lval >>= 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTC::TC("libtests", "Pl_ASCII85Decoder partial flush",
|
QTC::TC(
|
||||||
(this->pos == 5) ? 0 : 1);
|
"libtests",
|
||||||
|
"Pl_ASCII85Decoder partial flush",
|
||||||
|
(this->pos == 5) ? 0 : 1);
|
||||||
// Reset before calling getNext()->write in case that throws an
|
// Reset before calling getNext()->write in case that throws an
|
||||||
// exception.
|
// exception.
|
||||||
auto t = this->pos - 1;
|
auto t = this->pos - 1;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include <qpdf/Pl_ASCIIHexDecoder.hh>
|
#include <qpdf/Pl_ASCIIHexDecoder.hh>
|
||||||
|
|
||||||
#include <qpdf/QTC.hh>
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
|
Pl_ASCIIHexDecoder::Pl_ASCIIHexDecoder(char const* identifier, Pipeline* next) :
|
||||||
Pipeline(identifier, next),
|
Pipeline(identifier, next),
|
||||||
@ -22,53 +22,45 @@ Pl_ASCIIHexDecoder::~Pl_ASCIIHexDecoder()
|
|||||||
void
|
void
|
||||||
Pl_ASCIIHexDecoder::write(unsigned char* buf, size_t len)
|
Pl_ASCIIHexDecoder::write(unsigned char* buf, size_t len)
|
||||||
{
|
{
|
||||||
if (this->eod)
|
if (this->eod) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < len; ++i)
|
for (size_t i = 0; i < len; ++i) {
|
||||||
{
|
|
||||||
char ch = static_cast<char>(toupper(buf[i]));
|
char ch = static_cast<char>(toupper(buf[i]));
|
||||||
switch (ch)
|
switch (ch) {
|
||||||
{
|
case ' ':
|
||||||
case ' ':
|
case '\f':
|
||||||
case '\f':
|
case '\v':
|
||||||
case '\v':
|
case '\t':
|
||||||
case '\t':
|
case '\r':
|
||||||
case '\r':
|
case '\n':
|
||||||
case '\n':
|
|
||||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder ignore space");
|
QTC::TC("libtests", "Pl_ASCIIHexDecoder ignore space");
|
||||||
// ignore whitespace
|
// ignore whitespace
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
this->eod = true;
|
this->eod = true;
|
||||||
flush();
|
flush();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (((ch >= '0') && (ch <= '9')) ||
|
if (((ch >= '0') && (ch <= '9')) || ((ch >= 'A') && (ch <= 'F'))) {
|
||||||
((ch >= 'A') && (ch <= 'F')))
|
|
||||||
{
|
|
||||||
this->inbuf[this->pos++] = ch;
|
this->inbuf[this->pos++] = ch;
|
||||||
if (this->pos == 2)
|
if (this->pos == 2) {
|
||||||
{
|
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
char t[2];
|
char t[2];
|
||||||
t[0] = ch;
|
t[0] = ch;
|
||||||
t[1] = 0;
|
t[1] = 0;
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string("character out of range"
|
std::string("character out of range"
|
||||||
" during base Hex decode: ") + t);
|
" during base Hex decode: ") +
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (this->eod)
|
if (this->eod) {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,27 +69,24 @@ Pl_ASCIIHexDecoder::write(unsigned char* buf, size_t len)
|
|||||||
void
|
void
|
||||||
Pl_ASCIIHexDecoder::flush()
|
Pl_ASCIIHexDecoder::flush()
|
||||||
{
|
{
|
||||||
if (this->pos == 0)
|
if (this->pos == 0) {
|
||||||
{
|
|
||||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
|
QTC::TC("libtests", "Pl_ASCIIHexDecoder no-op flush");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int b[2];
|
int b[2];
|
||||||
for (int i = 0; i < 2; ++i)
|
for (int i = 0; i < 2; ++i) {
|
||||||
{
|
if (this->inbuf[i] >= 'A') {
|
||||||
if (this->inbuf[i] >= 'A')
|
|
||||||
{
|
|
||||||
b[i] = this->inbuf[i] - 'A' + 10;
|
b[i] = this->inbuf[i] - 'A' + 10;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
b[i] = this->inbuf[i] - '0';
|
b[i] = this->inbuf[i] - '0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsigned char ch = static_cast<unsigned char>((b[0] << 4) + b[1]);
|
unsigned char ch = static_cast<unsigned char>((b[0] << 4) + b[1]);
|
||||||
|
|
||||||
QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush",
|
QTC::TC(
|
||||||
(this->pos == 2) ? 0 : 1);
|
"libtests",
|
||||||
|
"Pl_ASCIIHexDecoder partial flush",
|
||||||
|
(this->pos == 2) ? 0 : 1);
|
||||||
// Reset before calling getNext()->write in case that throws an
|
// Reset before calling getNext()->write in case that throws an
|
||||||
// exception.
|
// exception.
|
||||||
this->pos = 0;
|
this->pos = 0;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#include <qpdf/Pl_Buffer.hh>
|
#include <qpdf/Pl_Buffer.hh>
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <stdexcept>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
Pl_Buffer::Members::Members() :
|
Pl_Buffer::Members::Members() :
|
||||||
ready(true),
|
ready(true),
|
||||||
@ -29,28 +29,24 @@ Pl_Buffer::~Pl_Buffer()
|
|||||||
void
|
void
|
||||||
Pl_Buffer::write(unsigned char* buf, size_t len)
|
Pl_Buffer::write(unsigned char* buf, size_t len)
|
||||||
{
|
{
|
||||||
if (this->m->data.get() == 0)
|
if (this->m->data.get() == 0) {
|
||||||
{
|
|
||||||
this->m->data = make_pointer_holder<Buffer>(len);
|
this->m->data = make_pointer_holder<Buffer>(len);
|
||||||
}
|
}
|
||||||
size_t cur_size = this->m->data->getSize();
|
size_t cur_size = this->m->data->getSize();
|
||||||
size_t left = cur_size - this->m->total_size;
|
size_t left = cur_size - this->m->total_size;
|
||||||
if (left < len)
|
if (left < len) {
|
||||||
{
|
|
||||||
size_t new_size = std::max(this->m->total_size + len, 2 * cur_size);
|
size_t new_size = std::max(this->m->total_size + len, 2 * cur_size);
|
||||||
auto b = make_pointer_holder<Buffer>(new_size);
|
auto b = make_pointer_holder<Buffer>(new_size);
|
||||||
memcpy(b->getBuffer(), this->m->data->getBuffer(), this->m->total_size);
|
memcpy(b->getBuffer(), this->m->data->getBuffer(), this->m->total_size);
|
||||||
this->m->data = b;
|
this->m->data = b;
|
||||||
}
|
}
|
||||||
if (len)
|
if (len) {
|
||||||
{
|
|
||||||
memcpy(this->m->data->getBuffer() + this->m->total_size, buf, len);
|
memcpy(this->m->data->getBuffer() + this->m->total_size, buf, len);
|
||||||
this->m->total_size += len;
|
this->m->total_size += len;
|
||||||
}
|
}
|
||||||
this->m->ready = false;
|
this->m->ready = false;
|
||||||
|
|
||||||
if (getNext(true))
|
if (getNext(true)) {
|
||||||
{
|
|
||||||
getNext()->write(buf, len);
|
getNext()->write(buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,8 +55,7 @@ void
|
|||||||
Pl_Buffer::finish()
|
Pl_Buffer::finish()
|
||||||
{
|
{
|
||||||
this->m->ready = true;
|
this->m->ready = true;
|
||||||
if (getNext(true))
|
if (getNext(true)) {
|
||||||
{
|
|
||||||
getNext()->finish();
|
getNext()->finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,14 +63,12 @@ Pl_Buffer::finish()
|
|||||||
Buffer*
|
Buffer*
|
||||||
Pl_Buffer::getBuffer()
|
Pl_Buffer::getBuffer()
|
||||||
{
|
{
|
||||||
if (! this->m->ready)
|
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);
|
Buffer* b = new Buffer(this->m->total_size);
|
||||||
if (this->m->total_size > 0)
|
if (this->m->total_size > 0) {
|
||||||
{
|
|
||||||
unsigned char* p = b->getBuffer();
|
unsigned char* p = b->getBuffer();
|
||||||
memcpy(p, this->m->data->getBuffer(), this->m->total_size);
|
memcpy(p, this->m->data->getBuffer(), this->m->total_size);
|
||||||
}
|
}
|
||||||
@ -90,22 +83,18 @@ Pl_Buffer::getBufferSharedPointer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Pl_Buffer::getMallocBuffer(unsigned char **buf, size_t* len)
|
Pl_Buffer::getMallocBuffer(unsigned char** buf, size_t* len)
|
||||||
{
|
{
|
||||||
if (! this->m->ready)
|
if (!this->m->ready) {
|
||||||
{
|
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"Pl_Buffer::getMallocBuffer() called when not ready");
|
"Pl_Buffer::getMallocBuffer() called when not ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
*len = this->m->total_size;
|
*len = this->m->total_size;
|
||||||
if (this->m->total_size > 0)
|
if (this->m->total_size > 0) {
|
||||||
{
|
|
||||||
*buf = reinterpret_cast<unsigned char*>(malloc(this->m->total_size));
|
*buf = reinterpret_cast<unsigned char*>(malloc(this->m->total_size));
|
||||||
memcpy(*buf, this->m->data->getBuffer(), this->m->total_size);
|
memcpy(*buf, this->m->data->getBuffer(), this->m->total_size);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
*buf = nullptr;
|
*buf = nullptr;
|
||||||
}
|
}
|
||||||
this->m = PointerHolder<Members>(new Members());
|
this->m = PointerHolder<Members>(new Members());
|
||||||
|
@ -33,4 +33,3 @@ Pl_Concatenate::manualFinish()
|
|||||||
{
|
{
|
||||||
getNext()->finish();
|
getNext()->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,7 @@ Pl_Count::~Pl_Count()
|
|||||||
void
|
void
|
||||||
Pl_Count::write(unsigned char* buf, size_t len)
|
Pl_Count::write(unsigned char* buf, size_t len)
|
||||||
{
|
{
|
||||||
if (len)
|
if (len) {
|
||||||
{
|
|
||||||
this->m->count += QIntC::to_offset(len);
|
this->m->count += QIntC::to_offset(len);
|
||||||
this->m->last_char = buf[len - 1];
|
this->m->last_char = buf[len - 1];
|
||||||
getNext()->write(buf, len);
|
getNext()->write(buf, len);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#include <qpdf/Pl_DCT.hh>
|
#include <qpdf/Pl_DCT.hh>
|
||||||
|
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <qpdf/QTC.hh>
|
|
||||||
#include <qpdf/QIntC.hh>
|
#include <qpdf/QIntC.hh>
|
||||||
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#if BITS_IN_JSAMPLE != 8
|
#if BITS_IN_JSAMPLE != 8
|
||||||
# error "qpdf does not support libjpeg built with BITS_IN_JSAMPLE != 8"
|
# error "qpdf does not support libjpeg built with BITS_IN_JSAMPLE != 8"
|
||||||
@ -32,13 +32,14 @@ error_handler(j_common_ptr cinfo)
|
|||||||
longjmp(jerr->jmpbuf, 1);
|
longjmp(jerr->jmpbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pl_DCT::Members::Members(action_e action,
|
Pl_DCT::Members::Members(
|
||||||
char const* buf_description,
|
action_e action,
|
||||||
JDIMENSION image_width,
|
char const* buf_description,
|
||||||
JDIMENSION image_height,
|
JDIMENSION image_width,
|
||||||
int components,
|
JDIMENSION image_height,
|
||||||
J_COLOR_SPACE color_space,
|
int components,
|
||||||
CompressConfig* config_callback) :
|
J_COLOR_SPACE color_space,
|
||||||
|
CompressConfig* config_callback) :
|
||||||
action(action),
|
action(action),
|
||||||
buf(buf_description),
|
buf(buf_description),
|
||||||
image_width(image_width),
|
image_width(image_width),
|
||||||
@ -59,15 +60,23 @@ Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next) :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Pl_DCT::Pl_DCT(char const* identifier, Pipeline* next,
|
Pl_DCT::Pl_DCT(
|
||||||
JDIMENSION image_width,
|
char const* identifier,
|
||||||
JDIMENSION image_height,
|
Pipeline* next,
|
||||||
int components,
|
JDIMENSION image_width,
|
||||||
J_COLOR_SPACE color_space,
|
JDIMENSION image_height,
|
||||||
CompressConfig* config_callback) :
|
int components,
|
||||||
|
J_COLOR_SPACE color_space,
|
||||||
|
CompressConfig* config_callback) :
|
||||||
Pipeline(identifier, next),
|
Pipeline(identifier, next),
|
||||||
m(new Members(a_compress, "DCT uncompressed image",
|
m(new Members(
|
||||||
image_width, image_height, components, color_space, config_callback))
|
a_compress,
|
||||||
|
"DCT uncompressed image",
|
||||||
|
image_width,
|
||||||
|
image_height,
|
||||||
|
components,
|
||||||
|
color_space,
|
||||||
|
config_callback))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,8 +99,7 @@ Pl_DCT::finish()
|
|||||||
// and decompress causes a memory leak with setjmp/longjmp. Just
|
// and decompress causes a memory leak with setjmp/longjmp. Just
|
||||||
// use a pointer and delete it.
|
// use a pointer and delete it.
|
||||||
Buffer* b = this->m->buf.getBuffer();
|
Buffer* b = this->m->buf.getBuffer();
|
||||||
if (b->getSize() == 0)
|
if (b->getSize() == 0) {
|
||||||
{
|
|
||||||
// Special case: empty data will never succeed and probably
|
// Special case: empty data will never succeed and probably
|
||||||
// means we're calling finish a second time from an exception
|
// means we're calling finish a second time from an exception
|
||||||
// handler.
|
// handler.
|
||||||
@ -111,44 +119,32 @@ Pl_DCT::finish()
|
|||||||
bool error = false;
|
bool error = false;
|
||||||
// The jpeg library is a "C" library, so we use setjmp and longjmp
|
// The jpeg library is a "C" library, so we use setjmp and longjmp
|
||||||
// for exception handling.
|
// for exception handling.
|
||||||
if (setjmp(jerr.jmpbuf) == 0)
|
if (setjmp(jerr.jmpbuf) == 0) {
|
||||||
{
|
try {
|
||||||
try
|
if (this->m->action == a_compress) {
|
||||||
{
|
|
||||||
if (this->m->action == a_compress)
|
|
||||||
{
|
|
||||||
compress(reinterpret_cast<void*>(&cinfo_compress), b);
|
compress(reinterpret_cast<void*>(&cinfo_compress), b);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
decompress(reinterpret_cast<void*>(&cinfo_decompress), b);
|
decompress(reinterpret_cast<void*>(&cinfo_decompress), b);
|
||||||
}
|
}
|
||||||
}
|
} catch (std::exception& e) {
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
// Convert an exception back to a longjmp so we can ensure
|
// Convert an exception back to a longjmp so we can ensure
|
||||||
// that the right cleanup happens. This will get converted
|
// that the right cleanup happens. This will get converted
|
||||||
// back to an exception.
|
// back to an exception.
|
||||||
jerr.msg = e.what();
|
jerr.msg = e.what();
|
||||||
longjmp(jerr.jmpbuf, 1);
|
longjmp(jerr.jmpbuf, 1);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
delete b;
|
delete b;
|
||||||
|
|
||||||
if (this->m->action == a_compress)
|
if (this->m->action == a_compress) {
|
||||||
{
|
|
||||||
jpeg_destroy_compress(&cinfo_compress);
|
jpeg_destroy_compress(&cinfo_compress);
|
||||||
}
|
}
|
||||||
if (this->m->action == a_decompress)
|
if (this->m->action == a_decompress) {
|
||||||
{
|
|
||||||
jpeg_destroy_decompress(&cinfo_decompress);
|
jpeg_destroy_decompress(&cinfo_decompress);
|
||||||
}
|
}
|
||||||
if (error)
|
if (error) {
|
||||||
{
|
|
||||||
throw std::runtime_error(jerr.msg);
|
throw std::runtime_error(jerr.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,8 +166,7 @@ static boolean
|
|||||||
empty_pipeline_output_buffer(j_compress_ptr cinfo)
|
empty_pipeline_output_buffer(j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
QTC::TC("libtests", "Pl_DCT empty_pipeline_output_buffer");
|
QTC::TC("libtests", "Pl_DCT empty_pipeline_output_buffer");
|
||||||
dct_pipeline_dest* dest =
|
dct_pipeline_dest* dest = reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
||||||
reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
|
||||||
dest->next->write(dest->buffer, dest->size);
|
dest->next->write(dest->buffer, dest->size);
|
||||||
dest->pub.next_output_byte = dest->buffer;
|
dest->pub.next_output_byte = dest->buffer;
|
||||||
dest->pub.free_in_buffer = dest->size;
|
dest->pub.free_in_buffer = dest->size;
|
||||||
@ -182,22 +177,20 @@ static void
|
|||||||
term_pipeline_destination(j_compress_ptr cinfo)
|
term_pipeline_destination(j_compress_ptr cinfo)
|
||||||
{
|
{
|
||||||
QTC::TC("libtests", "Pl_DCT term_pipeline_destination");
|
QTC::TC("libtests", "Pl_DCT term_pipeline_destination");
|
||||||
dct_pipeline_dest* dest =
|
dct_pipeline_dest* dest = reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
||||||
reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
|
||||||
dest->next->write(dest->buffer, dest->size - dest->pub.free_in_buffer);
|
dest->next->write(dest->buffer, dest->size - dest->pub.free_in_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
jpeg_pipeline_dest(j_compress_ptr cinfo,
|
jpeg_pipeline_dest(
|
||||||
unsigned char* outbuffer, size_t size,
|
j_compress_ptr cinfo, unsigned char* outbuffer, size_t size, Pipeline* next)
|
||||||
Pipeline* next)
|
|
||||||
{
|
{
|
||||||
cinfo->dest = static_cast<struct jpeg_destination_mgr *>(
|
cinfo->dest =
|
||||||
(*cinfo->mem->alloc_small)(reinterpret_cast<j_common_ptr>(cinfo),
|
static_cast<struct jpeg_destination_mgr*>((*cinfo->mem->alloc_small)(
|
||||||
JPOOL_PERMANENT,
|
reinterpret_cast<j_common_ptr>(cinfo),
|
||||||
sizeof(dct_pipeline_dest)));
|
JPOOL_PERMANENT,
|
||||||
dct_pipeline_dest* dest =
|
sizeof(dct_pipeline_dest)));
|
||||||
reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
dct_pipeline_dest* dest = reinterpret_cast<dct_pipeline_dest*>(cinfo->dest);
|
||||||
dest->pub.init_destination = init_pipeline_destination;
|
dest->pub.init_destination = init_pipeline_destination;
|
||||||
dest->pub.empty_output_buffer = empty_pipeline_output_buffer;
|
dest->pub.empty_output_buffer = empty_pipeline_output_buffer;
|
||||||
dest->pub.term_destination = term_pipeline_destination;
|
dest->pub.term_destination = term_pipeline_destination;
|
||||||
@ -224,20 +217,15 @@ fill_buffer_input_buffer(j_decompress_ptr)
|
|||||||
static void
|
static void
|
||||||
skip_buffer_input_data(j_decompress_ptr cinfo, long num_bytes)
|
skip_buffer_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||||
{
|
{
|
||||||
if (num_bytes < 0)
|
if (num_bytes < 0) {
|
||||||
{
|
throw std::runtime_error("reading jpeg: jpeg library requested"
|
||||||
throw std::runtime_error(
|
" skipping a negative number of bytes");
|
||||||
"reading jpeg: jpeg library requested"
|
|
||||||
" skipping a negative number of bytes");
|
|
||||||
}
|
}
|
||||||
size_t to_skip = QIntC::to_size(num_bytes);
|
size_t to_skip = QIntC::to_size(num_bytes);
|
||||||
if ((to_skip > 0) && (to_skip <= cinfo->src->bytes_in_buffer))
|
if ((to_skip > 0) && (to_skip <= cinfo->src->bytes_in_buffer)) {
|
||||||
{
|
|
||||||
cinfo->src->next_input_byte += to_skip;
|
cinfo->src->next_input_byte += to_skip;
|
||||||
cinfo->src->bytes_in_buffer -= to_skip;
|
cinfo->src->bytes_in_buffer -= to_skip;
|
||||||
}
|
} else if (to_skip != 0) {
|
||||||
else if (to_skip != 0)
|
|
||||||
{
|
|
||||||
cinfo->src->next_input_byte += cinfo->src->bytes_in_buffer;
|
cinfo->src->next_input_byte += cinfo->src->bytes_in_buffer;
|
||||||
cinfo->src->bytes_in_buffer = 0;
|
cinfo->src->bytes_in_buffer = 0;
|
||||||
}
|
}
|
||||||
@ -251,10 +239,10 @@ term_buffer_source(j_decompress_ptr)
|
|||||||
static void
|
static void
|
||||||
jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer)
|
jpeg_buffer_src(j_decompress_ptr cinfo, Buffer* buffer)
|
||||||
{
|
{
|
||||||
cinfo->src = reinterpret_cast<jpeg_source_mgr *>(
|
cinfo->src = reinterpret_cast<jpeg_source_mgr*>((*cinfo->mem->alloc_small)(
|
||||||
(*cinfo->mem->alloc_small)(reinterpret_cast<j_common_ptr>(cinfo),
|
reinterpret_cast<j_common_ptr>(cinfo),
|
||||||
JPOOL_PERMANENT,
|
JPOOL_PERMANENT,
|
||||||
sizeof(jpeg_source_mgr)));
|
sizeof(jpeg_source_mgr)));
|
||||||
|
|
||||||
jpeg_source_mgr* src = cinfo->src;
|
jpeg_source_mgr* src = cinfo->src;
|
||||||
src->init_source = init_buffer_source;
|
src->init_source = init_buffer_source;
|
||||||
@ -272,15 +260,17 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
|
|||||||
struct jpeg_compress_struct* cinfo =
|
struct jpeg_compress_struct* cinfo =
|
||||||
reinterpret_cast<jpeg_compress_struct*>(cinfo_p);
|
reinterpret_cast<jpeg_compress_struct*>(cinfo_p);
|
||||||
|
|
||||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
#if ( \
|
||||||
defined(__clang__))
|
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||||
# pragma GCC diagnostic push
|
defined(__clang__))
|
||||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||||
#endif
|
#endif
|
||||||
jpeg_create_compress(cinfo);
|
jpeg_create_compress(cinfo);
|
||||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
#if ( \
|
||||||
defined(__clang__))
|
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||||
# pragma GCC diagnostic pop
|
defined(__clang__))
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
static int const BUF_SIZE = 65536;
|
static int const BUF_SIZE = 65536;
|
||||||
auto outbuffer_ph = std::make_unique<unsigned char[]>(BUF_SIZE);
|
auto outbuffer_ph = std::make_unique<unsigned char[]>(BUF_SIZE);
|
||||||
@ -292,33 +282,29 @@ Pl_DCT::compress(void* cinfo_p, Buffer* b)
|
|||||||
cinfo->input_components = this->m->components;
|
cinfo->input_components = this->m->components;
|
||||||
cinfo->in_color_space = this->m->color_space;
|
cinfo->in_color_space = this->m->color_space;
|
||||||
jpeg_set_defaults(cinfo);
|
jpeg_set_defaults(cinfo);
|
||||||
if (this->m->config_callback)
|
if (this->m->config_callback) {
|
||||||
{
|
|
||||||
this->m->config_callback->apply(cinfo);
|
this->m->config_callback->apply(cinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
jpeg_start_compress(cinfo, TRUE);
|
jpeg_start_compress(cinfo, TRUE);
|
||||||
|
|
||||||
unsigned int width = cinfo->image_width *
|
unsigned int width =
|
||||||
QIntC::to_uint(cinfo->input_components);
|
cinfo->image_width * QIntC::to_uint(cinfo->input_components);
|
||||||
size_t expected_size =
|
size_t expected_size = QIntC::to_size(cinfo->image_height) *
|
||||||
QIntC::to_size(cinfo->image_height) *
|
|
||||||
QIntC::to_size(cinfo->image_width) *
|
QIntC::to_size(cinfo->image_width) *
|
||||||
QIntC::to_size(cinfo->input_components);
|
QIntC::to_size(cinfo->input_components);
|
||||||
if (b->getSize() != expected_size)
|
if (b->getSize() != expected_size) {
|
||||||
{
|
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"Pl_DCT: image buffer size = " +
|
"Pl_DCT: image buffer size = " +
|
||||||
QUtil::uint_to_string(b->getSize()) + "; expected size = " +
|
QUtil::uint_to_string(b->getSize()) +
|
||||||
QUtil::uint_to_string(expected_size));
|
"; expected size = " + QUtil::uint_to_string(expected_size));
|
||||||
}
|
}
|
||||||
JSAMPROW row_pointer[1];
|
JSAMPROW row_pointer[1];
|
||||||
unsigned char* buffer = b->getBuffer();
|
unsigned char* buffer = b->getBuffer();
|
||||||
while (cinfo->next_scanline < cinfo->image_height)
|
while (cinfo->next_scanline < cinfo->image_height) {
|
||||||
{
|
|
||||||
// We already verified that the buffer is big enough.
|
// We already verified that the buffer is big enough.
|
||||||
row_pointer[0] = &buffer[cinfo->next_scanline * width];
|
row_pointer[0] = &buffer[cinfo->next_scanline * width];
|
||||||
(void) jpeg_write_scanlines(cinfo, row_pointer, 1);
|
(void)jpeg_write_scanlines(cinfo, row_pointer, 1);
|
||||||
}
|
}
|
||||||
jpeg_finish_compress(cinfo);
|
jpeg_finish_compress(cinfo);
|
||||||
this->getNext()->finish();
|
this->getNext()->finish();
|
||||||
@ -330,33 +316,35 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b)
|
|||||||
struct jpeg_decompress_struct* cinfo =
|
struct jpeg_decompress_struct* cinfo =
|
||||||
reinterpret_cast<jpeg_decompress_struct*>(cinfo_p);
|
reinterpret_cast<jpeg_decompress_struct*>(cinfo_p);
|
||||||
|
|
||||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
#if ( \
|
||||||
defined(__clang__))
|
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||||
# pragma GCC diagnostic push
|
defined(__clang__))
|
||||||
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
# pragma GCC diagnostic push
|
||||||
|
# pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||||
#endif
|
#endif
|
||||||
jpeg_create_decompress(cinfo);
|
jpeg_create_decompress(cinfo);
|
||||||
#if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
#if ( \
|
||||||
defined(__clang__))
|
(defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || \
|
||||||
# pragma GCC diagnostic pop
|
defined(__clang__))
|
||||||
|
# pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
jpeg_buffer_src(cinfo, b);
|
jpeg_buffer_src(cinfo, b);
|
||||||
|
|
||||||
(void) jpeg_read_header(cinfo, TRUE);
|
(void)jpeg_read_header(cinfo, TRUE);
|
||||||
(void) jpeg_calc_output_dimensions(cinfo);
|
(void)jpeg_calc_output_dimensions(cinfo);
|
||||||
|
|
||||||
unsigned int width = cinfo->output_width *
|
unsigned int width =
|
||||||
QIntC::to_uint(cinfo->output_components);
|
cinfo->output_width * QIntC::to_uint(cinfo->output_components);
|
||||||
JSAMPARRAY buffer = (*cinfo->mem->alloc_sarray)
|
JSAMPARRAY buffer = (*cinfo->mem->alloc_sarray)(
|
||||||
(reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
|
reinterpret_cast<j_common_ptr>(cinfo), JPOOL_IMAGE, width, 1);
|
||||||
|
|
||||||
(void) jpeg_start_decompress(cinfo);
|
(void)jpeg_start_decompress(cinfo);
|
||||||
while (cinfo->output_scanline < cinfo->output_height)
|
while (cinfo->output_scanline < cinfo->output_height) {
|
||||||
{
|
(void)jpeg_read_scanlines(cinfo, buffer, 1);
|
||||||
(void) jpeg_read_scanlines(cinfo, buffer, 1);
|
this->getNext()->write(
|
||||||
this->getNext()->write(reinterpret_cast<unsigned char*>(buffer[0]),
|
reinterpret_cast<unsigned char*>(buffer[0]),
|
||||||
width * sizeof(buffer[0][0]));
|
width * sizeof(buffer[0][0]));
|
||||||
}
|
}
|
||||||
(void) jpeg_finish_decompress(cinfo);
|
(void)jpeg_finish_decompress(cinfo);
|
||||||
this->getNext()->finish();
|
this->getNext()->finish();
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user