mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-02 22:50:20 +00:00
Add command line option to copy encryption from other file
Add --copy-encryption and --encryption-file-password options to qpdf. Also strengthen test suite for copying encryption. The strengthened test suite would have caught the failure to preserve AES and the failure to update the file version, which was invalidating the encrypted data.
This commit is contained in:
parent
b26ce88ea1
commit
a101533e0a
12
ChangeLog
12
ChangeLog
@ -1,8 +1,18 @@
|
||||
2012-07-15 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* add new QPDF::isEncrypted method that returns some additional
|
||||
information beyond other versions.
|
||||
|
||||
* libqpdf/QPDFWriter.cc: fix copyEncryptionParameters to fix the
|
||||
minimum PDF version based on other file's encryption needs. This
|
||||
is a fix to code added on 2012-07-14 and did not impact previously
|
||||
released code.
|
||||
|
||||
* libqpdf/QPDFWriter.cc (copyEncryptionParameters): Bug fix: qpdf
|
||||
was not preserving whether or not AES encryption was being used
|
||||
when copying encryption parameters.
|
||||
when copying encryption parameters. The file would still have
|
||||
been properly encrypted, but a file that started off encrypted
|
||||
with AES could have become encrypted with RC4.
|
||||
|
||||
2012-07-14 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
|
8
TODO
8
TODO
@ -64,9 +64,11 @@ Next
|
||||
- Tests through qpdf command line: copy pages from multiple PDFs
|
||||
starting with one PDF and also starting with empty.
|
||||
|
||||
* qpdf commandline: provide an option to copy encryption parameters
|
||||
from another file, specifying file and password. Search for "Copy
|
||||
encryption parameters" in qpdf.test.
|
||||
* Document --copy-encryption and --encryption-file-password in
|
||||
manual. Mention that the first half of /ID as well as all the
|
||||
encryption parameters are copied. Maybe mention about StrF and
|
||||
StrM with respect to AES here and also with encryption
|
||||
preservation.
|
||||
|
||||
|
||||
Soon
|
||||
|
@ -248,6 +248,12 @@ class QPDF
|
||||
QPDF_DLL
|
||||
bool isEncrypted(int& R, int& P);
|
||||
|
||||
QPDF_DLL
|
||||
bool isEncrypted(int& R, int& P, int& V,
|
||||
encryption_method_e& stream_method,
|
||||
encryption_method_e& string_method,
|
||||
encryption_method_e& file_method);
|
||||
|
||||
// Encryption permissions -- not enforced by QPDF
|
||||
QPDF_DLL
|
||||
bool allowAccessibility();
|
||||
|
@ -743,6 +743,17 @@ QPDF::isEncrypted() const
|
||||
|
||||
bool
|
||||
QPDF::isEncrypted(int& R, int& P)
|
||||
{
|
||||
int V;
|
||||
encryption_method_e stream, string, file;
|
||||
return isEncrypted(R, P, V, stream, string, file);
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF::isEncrypted(int& R, int& P, int& V,
|
||||
encryption_method_e& stream_method,
|
||||
encryption_method_e& string_method,
|
||||
encryption_method_e& file_method)
|
||||
{
|
||||
if (this->encrypted)
|
||||
{
|
||||
@ -750,8 +761,13 @@ QPDF::isEncrypted(int& R, int& P)
|
||||
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
|
||||
QPDFObjectHandle Pkey = encrypt.getKey("/P");
|
||||
QPDFObjectHandle Rkey = encrypt.getKey("/R");
|
||||
QPDFObjectHandle Vkey = encrypt.getKey("/V");
|
||||
P = Pkey.getIntValue();
|
||||
R = Rkey.getIntValue();
|
||||
V = Vkey.getIntValue();
|
||||
stream_method = this->cf_stream;
|
||||
string_method = this->cf_stream;
|
||||
file_method = this->cf_file;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
125
qpdf/qpdf.cc
125
qpdf/qpdf.cc
@ -33,18 +33,29 @@ Usage: qpdf [ options ] infilename [ outfilename ]\n\
|
||||
\n\
|
||||
An option summary appears below. Please see the documentation for details.\n\
|
||||
\n\
|
||||
Note that when contradictory options are provided, whichever options are\n\
|
||||
provided last take precedence.\n\
|
||||
\n\
|
||||
\n\
|
||||
Basic Options\n\
|
||||
-------------\n\
|
||||
\n\
|
||||
--password=password specify a password for accessing encrypted files\n\
|
||||
--linearize generated a linearized (web optimized) file\n\
|
||||
--copy-encryption=file copy encryption parameters from specified file\n\
|
||||
--encryption-file-password=password\n\
|
||||
password used to open the file from which encryption\n\
|
||||
parameters are being copied\n\
|
||||
--encrypt options -- generate an encrypted file\n\
|
||||
--decrypt remove any encryption on the file\n\
|
||||
\n\
|
||||
If neither --encrypt or --decrypt are given, qpdf will preserve any\n\
|
||||
encryption data associated with a file.\n\
|
||||
If none of --copy-encryption, --encrypt or --decrypt are given, qpdf will\n\
|
||||
preserve any encryption data associated with a file.\n\
|
||||
\n\
|
||||
Note that when copying encryption parameters from another file, all\n\
|
||||
parameters will be copied, including both user and owner passwords, even\n\
|
||||
if the user password is used to open the other file. This works even if\n\
|
||||
the owner password is not known.\n\
|
||||
\n\
|
||||
Encryption Options\n\
|
||||
------------------\n\
|
||||
@ -192,12 +203,39 @@ static std::string show_bool(bool v)
|
||||
return v ? "allowed" : "not allowed";
|
||||
}
|
||||
|
||||
static std::string show_encryption_method(QPDF::encryption_method_e method)
|
||||
{
|
||||
std::string result = "unknown";
|
||||
switch (method)
|
||||
{
|
||||
case QPDF::e_none:
|
||||
result = "none";
|
||||
break;
|
||||
case QPDF::e_unknown:
|
||||
result = "unknown";
|
||||
break;
|
||||
case QPDF::e_rc4:
|
||||
result = "RC4";
|
||||
break;
|
||||
case QPDF::e_aes:
|
||||
result = "AESv2";
|
||||
break;
|
||||
// no default so gcc will warn for missing case
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void show_encryption(QPDF& pdf)
|
||||
{
|
||||
// Extract /P from /Encrypt
|
||||
int R = 0;
|
||||
int P = 0;
|
||||
if (! pdf.isEncrypted(R, P))
|
||||
int V = 0;
|
||||
QPDF::encryption_method_e stream_method = QPDF::e_unknown;
|
||||
QPDF::encryption_method_e string_method = QPDF::e_unknown;
|
||||
QPDF::encryption_method_e file_method = QPDF::e_unknown;
|
||||
if (! pdf.isEncrypted(R, P, V,
|
||||
stream_method, string_method, file_method))
|
||||
{
|
||||
std::cout << "File is not encrypted" << std::endl;
|
||||
}
|
||||
@ -206,25 +244,34 @@ static void show_encryption(QPDF& pdf)
|
||||
std::cout << "R = " << R << std::endl;
|
||||
std::cout << "P = " << P << std::endl;
|
||||
std::string user_password = pdf.getTrimmedUserPassword();
|
||||
std::cout << "User password = " << user_password << std::endl;
|
||||
std::cout << "extract for accessibility: "
|
||||
<< show_bool(pdf.allowAccessibility()) << std::endl;
|
||||
std::cout << "extract for any purpose: "
|
||||
<< show_bool(pdf.allowExtractAll()) << std::endl;
|
||||
std::cout << "print low resolution: "
|
||||
<< show_bool(pdf.allowPrintLowRes()) << std::endl;
|
||||
std::cout << "print high resolution: "
|
||||
<< show_bool(pdf.allowPrintHighRes()) << std::endl;
|
||||
std::cout << "modify document assembly: "
|
||||
<< show_bool(pdf.allowModifyAssembly()) << std::endl;
|
||||
std::cout << "modify forms: "
|
||||
<< show_bool(pdf.allowModifyForm()) << std::endl;
|
||||
std::cout << "modify annotations: "
|
||||
<< show_bool(pdf.allowModifyAnnotation()) << std::endl;
|
||||
std::cout << "modify other: "
|
||||
<< show_bool(pdf.allowModifyOther()) << std::endl;
|
||||
std::cout << "modify anything: "
|
||||
std::cout << "User password = " << user_password << std::endl
|
||||
<< "extract for accessibility: "
|
||||
<< show_bool(pdf.allowAccessibility()) << std::endl
|
||||
<< "extract for any purpose: "
|
||||
<< show_bool(pdf.allowExtractAll()) << std::endl
|
||||
<< "print low resolution: "
|
||||
<< show_bool(pdf.allowPrintLowRes()) << std::endl
|
||||
<< "print high resolution: "
|
||||
<< show_bool(pdf.allowPrintHighRes()) << std::endl
|
||||
<< "modify document assembly: "
|
||||
<< show_bool(pdf.allowModifyAssembly()) << std::endl
|
||||
<< "modify forms: "
|
||||
<< show_bool(pdf.allowModifyForm()) << std::endl
|
||||
<< "modify annotations: "
|
||||
<< show_bool(pdf.allowModifyAnnotation()) << std::endl
|
||||
<< "modify other: "
|
||||
<< show_bool(pdf.allowModifyOther()) << std::endl
|
||||
<< "modify anything: "
|
||||
<< show_bool(pdf.allowModifyAll()) << std::endl;
|
||||
if (V >= 4)
|
||||
{
|
||||
std::cout << "stream encryption method: "
|
||||
<< show_encryption_method(stream_method) << std::endl
|
||||
<< "string encryption method: "
|
||||
<< show_encryption_method(string_method) << std::endl
|
||||
<< "file encryption method: "
|
||||
<< show_encryption_method(file_method) << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,6 +626,10 @@ int main(int argc, char* argv[])
|
||||
bool linearize = false;
|
||||
bool decrypt = false;
|
||||
|
||||
bool copy_encryption = false;
|
||||
char const* encryption_file = 0;
|
||||
char const* encryption_file_password = "";
|
||||
|
||||
bool encrypt = false;
|
||||
std::string user_password;
|
||||
std::string owner_password;
|
||||
@ -664,11 +715,36 @@ int main(int argc, char* argv[])
|
||||
r3_accessibility, r3_extract, r3_print, r3_modify,
|
||||
force_V4, cleartext_metadata, use_aes);
|
||||
encrypt = true;
|
||||
decrypt = false;
|
||||
copy_encryption = false;
|
||||
}
|
||||
else if (strcmp(arg, "decrypt") == 0)
|
||||
{
|
||||
decrypt = true;
|
||||
encrypt = false;
|
||||
copy_encryption = false;
|
||||
}
|
||||
else if (strcmp(arg, "copy-encryption") == 0)
|
||||
{
|
||||
if (parameter == 0)
|
||||
{
|
||||
usage("--copy-encryption must be given as"
|
||||
"--copy_encryption=file");
|
||||
}
|
||||
encryption_file = parameter;
|
||||
copy_encryption = true;
|
||||
encrypt = false;
|
||||
decrypt = false;
|
||||
}
|
||||
else if (strcmp(arg, "encryption-file-password") == 0)
|
||||
{
|
||||
if (parameter == 0)
|
||||
{
|
||||
usage("--encryption-file-password must be given as"
|
||||
"--encryption-file-password=password");
|
||||
}
|
||||
encryption_file_password = parameter;
|
||||
}
|
||||
else if (strcmp(arg, "stream-data") == 0)
|
||||
{
|
||||
if (parameter == 0)
|
||||
@ -865,6 +941,7 @@ int main(int argc, char* argv[])
|
||||
try
|
||||
{
|
||||
QPDF pdf;
|
||||
QPDF encryption_pdf;
|
||||
if (ignore_xref_streams)
|
||||
{
|
||||
pdf.setIgnoreXRefStreams(true);
|
||||
@ -1082,6 +1159,12 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
w.setSuppressOriginalObjectIDs(true);
|
||||
}
|
||||
if (copy_encryption)
|
||||
{
|
||||
encryption_pdf.processFile(
|
||||
encryption_file, encryption_file_password);
|
||||
w.copyEncryptionParameters(encryption_pdf);
|
||||
}
|
||||
if (encrypt)
|
||||
{
|
||||
if (keylen == 40)
|
||||
|
@ -1271,7 +1271,7 @@ $td->runtest("linearize and encrypt file",
|
||||
$td->EXIT_STATUS => 0});
|
||||
$td->runtest("check encryption",
|
||||
{$td->COMMAND => "qpdf --show-encryption --password=owner a.pdf",
|
||||
$td->FILTER => "grep -v allowed"},
|
||||
$td->FILTER => "grep -v allowed | grep -v method"},
|
||||
{$td->STRING => "R = 4\nP = -4\nUser password = user\n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
@ -1290,7 +1290,7 @@ $td->runtest("encrypt with AES",
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("check encryption",
|
||||
{$td->COMMAND => "qpdf --show-encryption a.pdf",
|
||||
$td->FILTER => "grep -v allowed"},
|
||||
$td->FILTER => "grep -v allowed | grep -v method"},
|
||||
{$td->STRING => "R = 4\nP = -4\nUser password = \n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
@ -1311,7 +1311,7 @@ $td->runtest("linearize with AES and object streams",
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("check encryption",
|
||||
{$td->COMMAND => "qpdf --show-encryption a.pdf",
|
||||
$td->FILTER => "grep -v allowed"},
|
||||
$td->FILTER => "grep -v allowed | grep -v method"},
|
||||
{$td->STRING => "R = 4\nP = -4\nUser password = \n",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
@ -1345,7 +1345,7 @@ $td->runtest("make sure there is no xref stream",
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
# Look at some actual V4 files
|
||||
$n_tests += 10;
|
||||
$n_tests += 14;
|
||||
foreach my $d (['--force-V4', 'V4'],
|
||||
['--cleartext-metadata', 'V4-clearmeta'],
|
||||
['--use-aes=y', 'V4-aes'],
|
||||
@ -1359,6 +1359,10 @@ foreach my $d (['--force-V4', 'V4'],
|
||||
$td->runtest("check output",
|
||||
{$td->FILE => "a.pdf"},
|
||||
{$td->FILE => "$out.pdf"});
|
||||
$td->runtest("show encryption",
|
||||
{$td->COMMAND => "qpdf --show-encryption a.pdf"},
|
||||
{$td->FILE => "$out-encryption.out", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
}
|
||||
# Crypt Filter
|
||||
$td->runtest("decrypt with crypt filter",
|
||||
@ -1370,7 +1374,11 @@ $td->runtest("check output",
|
||||
{$td->FILE => 'decrypted-crypt-filter.pdf'});
|
||||
|
||||
# Copy encryption parameters
|
||||
$n_tests += 3;
|
||||
$n_tests += 10;
|
||||
$td->runtest("create reference qdf",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --qdf --no-original-object-ids minimal.pdf a.qdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("create encrypted file",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --encrypt user owner 128 --use-aes=y --extract=n --" .
|
||||
@ -1380,11 +1388,42 @@ $td->runtest("copy encryption parameters",
|
||||
{$td->COMMAND => "test_driver 30 minimal.pdf a.pdf"},
|
||||
{$td->STRING => "test 30 done\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("checkout encryption",
|
||||
$td->runtest("check output encryption",
|
||||
{$td->COMMAND => "qpdf --show-encryption b.pdf --password=owner"},
|
||||
{$td->FILE => "copied-encryption.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("convert to qdf",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --qdf b.pdf b.qdf" .
|
||||
" --password=owner --no-original-object-ids"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("compare qdf",
|
||||
{$td->COMMAND => "./diff-ignore-ID-version a.qdf b.qdf"},
|
||||
{$td->STRING => "okay\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("copy encryption with qpdf",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --copy-encryption=a.pdf".
|
||||
" --encryption-file-password=user" .
|
||||
" minimal.pdf c.pdf"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("check output encryption",
|
||||
{$td->COMMAND => "qpdf --show-encryption c.pdf --password=owner"},
|
||||
{$td->FILE => "copied-encryption.out",
|
||||
$td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
$td->runtest("convert to qdf",
|
||||
{$td->COMMAND =>
|
||||
"qpdf --qdf c.pdf c.qdf" .
|
||||
" --password=owner --no-original-object-ids"},
|
||||
{$td->STRING => "", $td->EXIT_STATUS => 0});
|
||||
$td->runtest("compare qdf",
|
||||
{$td->COMMAND => "./diff-ignore-ID-version a.qdf c.qdf"},
|
||||
{$td->STRING => "okay\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
@ -1753,6 +1792,5 @@ sub get_md5_checksum
|
||||
|
||||
sub cleanup
|
||||
{
|
||||
system("rm -rf *.ps *.pnm a.pdf a.qdf b.pdf b.qdf c.pdf" .
|
||||
" *.enc* tif1 tif2 tiff-cache");
|
||||
system("rm -rf *.ps *.pnm ?.pdf ?.qdf *.enc* tif1 tif2 tiff-cache");
|
||||
}
|
||||
|
15
qpdf/qtest/qpdf/V4-aes-clearmeta-encryption.out
Normal file
15
qpdf/qtest/qpdf/V4-aes-clearmeta-encryption.out
Normal file
@ -0,0 +1,15 @@
|
||||
R = 4
|
||||
P = -4
|
||||
User password =
|
||||
extract for accessibility: allowed
|
||||
extract for any purpose: allowed
|
||||
print low resolution: allowed
|
||||
print high resolution: allowed
|
||||
modify document assembly: allowed
|
||||
modify forms: allowed
|
||||
modify annotations: allowed
|
||||
modify other: allowed
|
||||
modify anything: allowed
|
||||
stream encryption method: AESv2
|
||||
string encryption method: AESv2
|
||||
file encryption method: AESv2
|
15
qpdf/qtest/qpdf/V4-aes-encryption.out
Normal file
15
qpdf/qtest/qpdf/V4-aes-encryption.out
Normal file
@ -0,0 +1,15 @@
|
||||
R = 4
|
||||
P = -4
|
||||
User password =
|
||||
extract for accessibility: allowed
|
||||
extract for any purpose: allowed
|
||||
print low resolution: allowed
|
||||
print high resolution: allowed
|
||||
modify document assembly: allowed
|
||||
modify forms: allowed
|
||||
modify annotations: allowed
|
||||
modify other: allowed
|
||||
modify anything: allowed
|
||||
stream encryption method: AESv2
|
||||
string encryption method: AESv2
|
||||
file encryption method: AESv2
|
15
qpdf/qtest/qpdf/V4-clearmeta-encryption.out
Normal file
15
qpdf/qtest/qpdf/V4-clearmeta-encryption.out
Normal file
@ -0,0 +1,15 @@
|
||||
R = 4
|
||||
P = -4
|
||||
User password =
|
||||
extract for accessibility: allowed
|
||||
extract for any purpose: allowed
|
||||
print low resolution: allowed
|
||||
print high resolution: allowed
|
||||
modify document assembly: allowed
|
||||
modify forms: allowed
|
||||
modify annotations: allowed
|
||||
modify other: allowed
|
||||
modify anything: allowed
|
||||
stream encryption method: RC4
|
||||
string encryption method: RC4
|
||||
file encryption method: RC4
|
15
qpdf/qtest/qpdf/V4-encryption.out
Normal file
15
qpdf/qtest/qpdf/V4-encryption.out
Normal file
@ -0,0 +1,15 @@
|
||||
R = 4
|
||||
P = -4
|
||||
User password =
|
||||
extract for accessibility: allowed
|
||||
extract for any purpose: allowed
|
||||
print low resolution: allowed
|
||||
print high resolution: allowed
|
||||
modify document assembly: allowed
|
||||
modify forms: allowed
|
||||
modify annotations: allowed
|
||||
modify other: allowed
|
||||
modify anything: allowed
|
||||
stream encryption method: RC4
|
||||
string encryption method: RC4
|
||||
file encryption method: RC4
|
@ -10,3 +10,6 @@ modify forms: allowed
|
||||
modify annotations: allowed
|
||||
modify other: allowed
|
||||
modify anything: allowed
|
||||
stream encryption method: AESv2
|
||||
string encryption method: AESv2
|
||||
file encryption method: AESv2
|
||||
|
8
qpdf/qtest/qpdf/diff-ignore-ID-version
Executable file
8
qpdf/qtest/qpdf/diff-ignore-ID-version
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
lines=$(expr + $(diff $1 $2 | egrep '^[<>]' | \
|
||||
egrep -v '/ID' | egrep -v '%PDF-' | wc -l))
|
||||
if [ "$lines" = "0" ]; then
|
||||
echo okay
|
||||
else
|
||||
diff -a -U 0 $1 $2
|
||||
fi
|
@ -58,12 +58,17 @@ class Provider: public QPDFObjectHandle::StreamDataProvider
|
||||
bool bad_length;
|
||||
};
|
||||
|
||||
static void checkPageContents(QPDFObjectHandle page,
|
||||
std::string const& wanted_string)
|
||||
static std::string getPageContents(QPDFObjectHandle page)
|
||||
{
|
||||
PointerHolder<Buffer> b1 =
|
||||
page.getKey("/Contents").getStreamData();
|
||||
std::string contents = std::string((char *)(b1->getBuffer()));
|
||||
return std::string((char *)(b1->getBuffer()), b1->getSize()) + "\0";
|
||||
}
|
||||
|
||||
static void checkPageContents(QPDFObjectHandle page,
|
||||
std::string const& wanted_string)
|
||||
{
|
||||
std::string contents = getPageContents(page);
|
||||
if (contents.find(wanted_string) == std::string::npos)
|
||||
{
|
||||
std::cout << "didn't find " << wanted_string << " in "
|
||||
@ -1030,10 +1035,24 @@ void runtest(int n, char const* filename1, char const* filename2)
|
||||
QPDF encrypted;
|
||||
encrypted.processFile(filename2, "user");
|
||||
QPDFWriter w(pdf, "b.pdf");
|
||||
w.setStaticID(true);
|
||||
w.setStreamDataMode(qpdf_s_preserve);
|
||||
w.copyEncryptionParameters(encrypted);
|
||||
w.write();
|
||||
|
||||
// Make sure the contents are actually the same
|
||||
QPDF final;
|
||||
final.processFile("b.pdf", "user");
|
||||
std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
|
||||
std::string orig_contents = getPageContents(pages[0]);
|
||||
pages = final.getAllPages();
|
||||
std::string new_contents = getPageContents(pages[0]);
|
||||
if (orig_contents != new_contents)
|
||||
{
|
||||
std::cout << "oops -- page contents don't match" << std::endl
|
||||
<< "original:\n" << orig_contents
|
||||
<< "new:\n" << new_contents
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user