From 734ac1e1d2b3ce10a2da1a7e736a30bdf0bc5cf8 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 19 Oct 2009 01:58:31 +0000 Subject: deal with stream-specific crypt filters git-svn-id: svn+q:///qpdf/trunk@827 71b93d88-0707-0410-a8cf-f5a4172ac649 --- libqpdf/QPDFObjectHandle.cc | 23 +++++++++++++++++++++++ libqpdf/QPDF_Stream.cc | 16 ++++++++++++++-- libqpdf/QPDF_encryption.cc | 25 +++++++++++++------------ 3 files changed, 50 insertions(+), 14 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 08d648bd..c3a7167b 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -258,6 +258,29 @@ QPDFObjectHandle::getKeys() return dynamic_cast(obj.getPointer())->getKeys(); } +// Array and Name accessors +bool +QPDFObjectHandle::isOrHasName(std::string const& value) +{ + if (isName() && (getName() == value)) + { + return true; + } + else if (isArray()) + { + int n = getArrayNItems(); + for (int i = 0; i < n; ++i) + { + QPDFObjectHandle item = getArrayItem(0); + if (item.isName() && (item.getName() == value)) + { + return true; + } + } + } + return false; +} + // Dictionary mutators void diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index a9e2ec51..6642a06e 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -136,6 +136,13 @@ QPDF_Stream::filterable(std::vector& filters, filterable = false; } } + else if (((key == "/Type") || (key == "/Name")) && + decode_obj.getKey("/Type").isName() && + (decode_obj.getKey("/Type").getName() == + "/CryptFilterDecodeParms")) + { + // we handle this in decryptStream + } else { filterable = false; @@ -212,7 +219,8 @@ QPDF_Stream::filterable(std::vector& filters, iter != filters.end(); ++iter) { std::string const& filter = *iter; - if (! ((filter == "/FlateDecode") || + if (! ((filter == "/Crypt") || + (filter == "/FlateDecode") || (filter == "/LZWDecode") || (filter == "/ASCII85Decode") || (filter == "/ASCIIHexDecode"))) @@ -266,7 +274,11 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter, iter != filters.rend(); ++iter) { std::string const& filter = *iter; - if (filter == "/FlateDecode") + if (filter == "/Crypt") + { + // Ignore -- handled by pipeStreamData + } + else if (filter == "/FlateDecode") { if (predictor == 12) { diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index fa16f55d..8962624d 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -600,18 +600,19 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, encryption_method_e method = e_unknown; std::string method_source = "/StmF from /Encrypt dictionary"; - // NOTE: the section in the PDF specification on crypt filters - // seems to suggest that there might be a /Crypt key in - // /DecodeParms whose value is a crypt filter (.e.g., << /Name - // /StdCF >>), but implementation notes suggest this can only - // happen for metadata streams, and emperical observation - // suggests that they are otherwise ignored. Not having been - // able to find a sample file that uses crypt filters in any - // way other than /StrF and /StmF, I'm not really sure what to - // do about this. If we were to override the encryption on a - // per-stream basis using crypt filters, set method_source to - // something useful in the error message for unknown - // encryption methods (search for method_source). + 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 (method == e_unknown) { -- cgit v1.2.3-54-g00ecf