2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-03 19:00:51 +00:00

Add public QPDFWriter::copyEncryptionParameters

Method to copy encryption parameters from another file.  Adapted from
existing code to copy encryption parameters from the original file.
This commit is contained in:
Jay Berkenbilt 2012-07-14 09:13:49 -04:00
parent ee3682f106
commit 0575d77d77
7 changed files with 57 additions and 8 deletions

View File

@ -1,5 +1,8 @@
2012-07-14 Jay Berkenbilt <ejb@ql.org> 2012-07-14 Jay Berkenbilt <ejb@ql.org>
* QPDFWriter: add public copyEncryptionParameters to allow copying
encryption parameters from another file.
* QPDFWriter: detect if the user has inserted an indirect object * QPDFWriter: detect if the user has inserted an indirect object
from another QPDF object and throw an exception directing the user from another QPDF object and throw an exception directing the user
to copyForeignObject. to copyForeignObject.

7
TODO
View File

@ -64,10 +64,9 @@ Next
- Tests through qpdf command line: copy pages from multiple PDFs - Tests through qpdf command line: copy pages from multiple PDFs
starting with one PDF and also starting with empty. starting with one PDF and also starting with empty.
* (Hopefully) Provide an option to copy encryption parameters from * qpdf commandline: provide an option to copy encryption parameters
another file. This would make it possible to decrypt a file, from another file, specifying file and password. Search for "Copy
manually work with it, and then re-encrypt it using the original encryption parameters" in qpdf.test.
encryption parameters including a possibly unknown owner password.
Soon Soon

View File

@ -188,6 +188,11 @@ class QPDFWriter
QPDF_DLL QPDF_DLL
void setPreserveEncryption(bool); void setPreserveEncryption(bool);
// Copy encryption parameters from another QPDF object. If you
// want to copy encryption from the object you are writing, call
// setPreserveEncryption(true) instead.
void copyEncryptionParameters(QPDF&);
// Set up for encrypted output. Disables stream prefiltering and // Set up for encrypted output. Disables stream prefiltering and
// content normalization. Note that setting R2 encryption // content normalization. Note that setting R2 encryption
// parameters sets the PDF version to at least 1.3, setting R3 // parameters sets the PDF version to at least 1.3, setting R3
@ -269,7 +274,6 @@ class QPDFWriter
int V, int R, int key_len, long P, int V, int R, int key_len, long P,
std::string const& O, std::string const& U, std::string const& O, std::string const& U,
std::string const& id1, std::string const& user_password); std::string const& id1, std::string const& user_password);
void copyEncryptionParameters();
void setDataKey(int objid); void setDataKey(int objid);
int openObject(int objid = 0); int openObject(int objid = 0);
void closeObject(int objid); void closeObject(int objid);

View File

@ -389,10 +389,11 @@ QPDFWriter::setEncryptionParameters(
} }
void void
QPDFWriter::copyEncryptionParameters() QPDFWriter::copyEncryptionParameters(QPDF& qpdf)
{ {
this->preserve_encryption = false;
generateID(); generateID();
QPDFObjectHandle trailer = this->pdf.getTrailer(); QPDFObjectHandle trailer = qpdf.getTrailer();
if (trailer.hasKey("/Encrypt")) if (trailer.hasKey("/Encrypt"))
{ {
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt"); QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
@ -410,6 +411,8 @@ QPDFWriter::copyEncryptionParameters()
} }
QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", QTC::TC("qpdf", "QPDFWriter copy encrypt metadata",
this->encrypt_metadata ? 0 : 1); this->encrypt_metadata ? 0 : 1);
this->id1 =
trailer.getKey("/ID").getArrayItem(0).getStringValue();
setEncryptionParametersInternal( setEncryptionParametersInternal(
V, V,
encrypt.getKey("/R").getIntValue(), encrypt.getKey("/R").getIntValue(),
@ -1625,7 +1628,7 @@ QPDFWriter::write()
if (preserve_encryption) if (preserve_encryption)
{ {
copyEncryptionParameters(); copyEncryptionParameters(this->pdf);
} }
if (! this->forced_pdf_version.empty()) if (! this->forced_pdf_version.empty())

View File

@ -1369,6 +1369,23 @@ $td->runtest("check output",
{$td->FILE => 'a.pdf'}, {$td->FILE => 'a.pdf'},
{$td->FILE => 'decrypted-crypt-filter.pdf'}); {$td->FILE => 'decrypted-crypt-filter.pdf'});
# Copy encryption parameters
$n_tests += 3;
$td->runtest("create encrypted file",
{$td->COMMAND =>
"qpdf --encrypt user owner 128 --use-aes=y --extract=n --" .
" minimal.pdf a.pdf"},
{$td->STRING => "", $td->EXIT_STATUS => 0});
$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->COMMAND => "qpdf --show-encryption b.pdf --password=owner"},
{$td->FILE => "copied-encryption.out",
$td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
show_ntests(); show_ntests();
# ---------- # ----------
$td->notify("--- Content Preservation Tests ---"); $td->notify("--- Content Preservation Tests ---");

View File

@ -0,0 +1,12 @@
R = 4
P = -20
User password = user
extract for accessibility: allowed
extract for any purpose: not 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

View File

@ -1024,6 +1024,17 @@ void runtest(int n, char const* filename1, char const* filename2)
std::cout << "logic error: " << e.what() << std::endl; std::cout << "logic error: " << e.what() << std::endl;
} }
} }
else if (n == 30)
{
assert(filename2 != 0);
QPDF encrypted;
encrypted.processFile(filename2, "user");
QPDFWriter w(pdf, "b.pdf");
w.setStaticID(true);
w.setStreamDataMode(qpdf_s_preserve);
w.copyEncryptionParameters(encrypted);
w.write();
}
else else
{ {
throw std::runtime_error(std::string("invalid test ") + throw std::runtime_error(std::string("invalid test ") +