aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDF_encryption.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2012-12-30 01:00:05 +0100
committerJay Berkenbilt <ejb@ql.org>2012-12-31 16:32:32 +0100
commit93ac1695a4b79f3d5b71e2d57ed876c28866d2c9 (patch)
tree7b202d0056fd5f1599a7ac0fe6c7cdf152440d0d /libqpdf/QPDF_encryption.cc
parenteff2c9a67937b875d578b8a744070516f91930e2 (diff)
downloadqpdf-93ac1695a4b79f3d5b71e2d57ed876c28866d2c9.tar.zst
Support files with only attachments encrypted
Test cases added in a future commit since they depend on /R=6 support.
Diffstat (limited to 'libqpdf/QPDF_encryption.cc')
-rw-r--r--libqpdf/QPDF_encryption.cc91
1 files changed, 51 insertions, 40 deletions
diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc
index 6ab51a03..568b8771 100644
--- a/libqpdf/QPDF_encryption.cc
+++ b/libqpdf/QPDF_encryption.cc
@@ -573,28 +573,6 @@ QPDF::initializeEncryption()
{
this->cf_file = this->cf_stream;
}
- if (this->cf_file != this->cf_stream)
- {
- // The issue for qpdf is that it can't tell the difference
- // between an embedded file stream and a regular stream.
- // Search for a comment containing cf_file. To fix this,
- // we need files with encrypted embedded files and
- // non-encrypted native streams and vice versa. Also if
- // it is possible for them to be encrypted in different
- // ways, we should have some of those too. In cases where
- // we can detect whether a stream is encrypted or not, we
- // might want to try to detecet that automatically in
- // defense of possible logic errors surrounding detection
- // of embedded file streams, unless that's really clear
- // from the specification.
- throw QPDFExc(qpdf_e_unsupported, this->file->getName(),
- "encryption dictionary", this->file->getLastOffset(),
- "This document has embedded files that are"
- " encrypted differently from the rest of the file."
- " qpdf does not presently support this due to"
- " lack of test data; if possible, please submit"
- " a bug report that includes this file.");
- }
}
EncryptionData data(V, R, Length / 8, P, O, U, "", "", "",
id1, this->encrypt_metadata);
@@ -737,18 +715,48 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation,
encryption_method_e method = e_unknown;
std::string method_source = "/StmF from /Encrypt dictionary";
- if (stream_dict.getKey("/Filter").isOrHasName("/Crypt") &&
- stream_dict.getKey("/DecodeParms").isDictionary())
- {
- QPDFObjectHandle decode_parms = stream_dict.getKey("/DecodeParms");
- if (decode_parms.getKey("/Type").isName() &&
- (decode_parms.getKey("/Type").getName() ==
- "/CryptFilterDecodeParms"))
- {
- QTC::TC("qpdf", "QPDF_encryption stream crypt filter");
- method = interpretCF(decode_parms.getKey("/Name"));
- method_source = "stream's Crypt decode parameters";
- }
+ if (stream_dict.getKey("/Filter").isOrHasName("/Crypt"))
+ {
+ if (stream_dict.getKey("/DecodeParms").isDictionary())
+ {
+ QPDFObjectHandle decode_parms =
+ stream_dict.getKey("/DecodeParms");
+ if (decode_parms.getKey("/Type").isName() &&
+ (decode_parms.getKey("/Type").getName() ==
+ "/CryptFilterDecodeParms"))
+ {
+ QTC::TC("qpdf", "QPDF_encryption stream crypt filter");
+ method = interpretCF(decode_parms.getKey("/Name"));
+ method_source = "stream's Crypt decode parameters";
+ }
+ }
+ else if (stream_dict.getKey("/DecodeParms").isArray() &&
+ stream_dict.getKey("/Filter").isArray())
+ {
+ QPDFObjectHandle filter = stream_dict.getKey("/Filter");
+ QPDFObjectHandle decode = stream_dict.getKey("/DecodeParms");
+ if (filter.getArrayNItems() == decode.getArrayNItems())
+ {
+ for (int i = 0; i < filter.getArrayNItems(); ++i)
+ {
+ if (filter.getArrayItem(i).isName() &&
+ (filter.getArrayItem(i).getName() == "/Crypt"))
+ {
+ QPDFObjectHandle crypt_params =
+ decode.getArrayItem(i);
+ if (crypt_params.isDictionary() &&
+ crypt_params.getKey("/Name").isName())
+ {
+// XXX QTC::TC("qpdf", "QPDF_encrypt crypt array");
+ method = interpretCF(
+ crypt_params.getKey("/Name"));
+ method_source = "stream's Crypt "
+ "decode parameters (array)";
+ }
+ }
+ }
+ }
+ }
}
if (method == e_unknown)
@@ -760,12 +768,15 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation,
}
else
{
- // NOTE: We should should use cf_file if this is an
- // embedded file, but we can't yet detect embedded
- // file streams as such. When fixing, search for all
- // occurrences of cf_file to find a reference to this
- // comment.
- method = this->cf_stream;
+ if (this->attachment_streams.count(
+ ObjGen(objid, generation)) > 0)
+ {
+ method = this->cf_file;
+ }
+ else
+ {
+ method = this->cf_stream;
+ }
}
}
use_aes = false;