From 5a842792b69550cf441d4598feb1daff2fa8c83f Mon Sep 17 00:00:00 2001 From: Masamichi Hosoda Date: Fri, 18 Oct 2019 19:41:53 +0900 Subject: Parse Contents in signature dictionary without encryption Various PDF digital signing tools do not encrypt /Contents value in signature dictionary. Adobe Acrobat Reader DC can handle a PDF with the /Contents value not encrypted. Write Contents in signature dictionary without encryption Tests ensure that string /Contents are not handled specially when not found in sig dicts. --- libqpdf/QPDFObjectHandle.cc | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index d49976b6..3dacfb8e 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -1779,12 +1779,19 @@ QPDFObjectHandle::parseInternal(PointerHolder input, bool done = false; int bad_count = 0; int good_count = 0; + bool b_contents = false; + std::vector contents_string_stack; + contents_string_stack.push_back(""); + std::vector contents_offset_stack; + contents_offset_stack.push_back(-1); while (! done) { bool bad = false; SparseOHArray& olist = olist_stack.back(); parser_state_e state = state_stack.back(); offset = offset_stack.back(); + std::string& contents_string = contents_string_stack.back(); + qpdf_offset_t& contents_offset = contents_offset_stack.back(); object = QPDFObjectHandle(); set_offset = false; @@ -1894,6 +1901,9 @@ QPDFObjectHandle::parseInternal(PointerHolder input, state_stack.push_back( (token.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary); + b_contents = false; + contents_string_stack.push_back(""); + contents_offset_stack.push_back(-1); } break; @@ -1914,7 +1924,19 @@ QPDFObjectHandle::parseInternal(PointerHolder input, break; case QPDFTokenizer::tt_name: - object = newName(token.getValue()); + { + std::string name = token.getValue(); + object = newName(name); + + if (name == "/Contents") + { + b_contents = true; + } + else + { + b_contents = false; + } + } break; case QPDFTokenizer::tt_word: @@ -1975,6 +1997,12 @@ QPDFObjectHandle::parseInternal(PointerHolder input, std::string val = token.getValue(); if (decrypter) { + if (b_contents) + { + contents_string = val; + contents_offset = input->getLastOffset(); + b_contents = false; + } decrypter->decryptString(val); } object = QPDFObjectHandle::newString(val); @@ -2168,6 +2196,18 @@ QPDFObjectHandle::parseInternal(PointerHolder input, } dict[key] = val; } + if (!contents_string.empty() && + dict.count("/Type") && + dict["/Type"].isName() && + dict["/Type"].getName() == "/Sig" && + dict.count("/ByteRange") && + dict.count("/Contents") && + dict["/Contents"].isString()) + { + dict["/Contents"] + = QPDFObjectHandle::newString(contents_string); + dict["/Contents"].setParsedOffset(contents_offset); + } object = newDictionary(dict); setObjectDescriptionFromInput( object, context, object_description, input, offset); @@ -2190,6 +2230,8 @@ QPDFObjectHandle::parseInternal(PointerHolder input, { olist_stack.back().append(object); } + contents_string_stack.pop_back(); + contents_offset_stack.pop_back(); } } -- cgit v1.2.3-54-g00ecf