| // Copyright 2020 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "public/fpdf_signature.h" |
| |
| #include <vector> |
| |
| #include "core/fpdfapi/parser/cpdf_array.h" |
| #include "core/fpdfapi/parser/cpdf_dictionary.h" |
| #include "core/fpdfapi/parser/cpdf_document.h" |
| #include "core/fxcrt/stl_util.h" |
| #include "fpdfsdk/cpdfsdk_helpers.h" |
| |
| namespace { |
| |
| std::vector<CPDF_Dictionary*> CollectSignatures(CPDF_Document* doc) { |
| std::vector<CPDF_Dictionary*> signatures; |
| CPDF_Dictionary* root = doc->GetRoot(); |
| if (!root) |
| return signatures; |
| |
| const CPDF_Dictionary* acro_form = root->GetDictFor("AcroForm"); |
| if (!acro_form) |
| return signatures; |
| |
| const CPDF_Array* fields = acro_form->GetArrayFor("Fields"); |
| if (!fields) |
| return signatures; |
| |
| CPDF_ArrayLocker locker(fields); |
| for (auto& field : locker) { |
| CPDF_Dictionary* field_dict = field->GetDict(); |
| if (field_dict && field_dict->GetNameFor("FT") == "Sig") |
| signatures.push_back(field_dict); |
| } |
| return signatures; |
| } |
| |
| } // namespace |
| |
| FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document) { |
| auto* doc = CPDFDocumentFromFPDFDocument(document); |
| if (!doc) |
| return -1; |
| |
| return fxcrt::CollectionSize<int>(CollectSignatures(doc)); |
| } |
| |
| FPDF_EXPORT FPDF_SIGNATURE FPDF_CALLCONV |
| FPDF_GetSignatureObject(FPDF_DOCUMENT document, int index) { |
| auto* doc = CPDFDocumentFromFPDFDocument(document); |
| if (!doc) |
| return nullptr; |
| |
| std::vector<CPDF_Dictionary*> signatures = CollectSignatures(doc); |
| if (!fxcrt::IndexInBounds(signatures, index)) |
| return nullptr; |
| |
| return FPDFSignatureFromCPDFDictionary(signatures[index]); |
| } |
| |
| FPDF_EXPORT unsigned long FPDF_CALLCONV |
| FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature, |
| void* buffer, |
| unsigned long length) { |
| CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); |
| if (!signature_dict) |
| return 0; |
| |
| CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); |
| if (!value_dict) |
| return 0; |
| |
| ByteString contents = value_dict->GetStringFor("Contents"); |
| unsigned long contents_len = contents.GetLength(); |
| if (buffer && length >= contents_len) |
| memcpy(buffer, contents.c_str(), contents_len); |
| |
| return contents_len; |
| } |
| |
| FPDF_EXPORT unsigned long FPDF_CALLCONV |
| FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature, |
| int* buffer, |
| unsigned long length) { |
| CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); |
| if (!signature_dict) |
| return 0; |
| |
| CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); |
| if (!value_dict) |
| return 0; |
| |
| const CPDF_Array* byte_range = value_dict->GetArrayFor("ByteRange"); |
| if (!byte_range) |
| return 0; |
| |
| unsigned long byte_range_len = byte_range->size(); |
| if (buffer && length >= byte_range_len) { |
| for (size_t i = 0; i < byte_range_len; ++i) |
| buffer[i] = byte_range->GetIntegerAt(i); |
| } |
| |
| return byte_range_len; |
| } |
| |
| FPDF_EXPORT unsigned long FPDF_CALLCONV |
| FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature, |
| char* buffer, |
| unsigned long length) { |
| CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); |
| if (!signature_dict) |
| return 0; |
| |
| CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); |
| if (!value_dict || !value_dict->KeyExist("SubFilter")) |
| return 0; |
| |
| ByteString sub_filter = value_dict->GetNameFor("SubFilter"); |
| return NulTerminateMaybeCopyAndReturnLength(sub_filter, buffer, length); |
| } |
| |
| FPDF_EXPORT unsigned long FPDF_CALLCONV |
| FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature, |
| void* buffer, |
| unsigned long length) { |
| CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); |
| if (!signature_dict) |
| return 0; |
| |
| CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); |
| if (!value_dict) |
| return 0; |
| |
| const CPDF_Object* obj = value_dict->GetObjectFor("Reason"); |
| if (!obj || !obj->IsString()) |
| return 0; |
| |
| return Utf16EncodeMaybeCopyAndReturnLength(obj->GetUnicodeText(), buffer, |
| length); |
| } |
| |
| FPDF_EXPORT unsigned long FPDF_CALLCONV |
| FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature, |
| char* buffer, |
| unsigned long length) { |
| CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); |
| if (!signature_dict) |
| return 0; |
| |
| CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); |
| if (!value_dict) |
| return 0; |
| |
| const CPDF_Object* obj = value_dict->GetObjectFor("M"); |
| if (!obj || !obj->IsString()) |
| return 0; |
| |
| return NulTerminateMaybeCopyAndReturnLength(obj->GetString(), buffer, length); |
| } |
| |
| FPDF_EXPORT unsigned int FPDF_CALLCONV |
| FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature) { |
| int permission = 0; |
| CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature); |
| if (!signature_dict) |
| return permission; |
| |
| CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V"); |
| if (!value_dict) |
| return permission; |
| |
| CPDF_Array* references = value_dict->GetArrayFor("Reference"); |
| if (!references) |
| return permission; |
| |
| CPDF_ArrayLocker locker(references); |
| for (auto& reference : locker) { |
| CPDF_Dictionary* reference_dict = reference->GetDict(); |
| if (!reference_dict) |
| continue; |
| |
| ByteString transform_method = reference_dict->GetNameFor("TransformMethod"); |
| if (transform_method != "DocMDP") |
| continue; |
| |
| CPDF_Dictionary* transform_params = |
| reference_dict->GetDictFor("TransformParams"); |
| if (!transform_params) |
| continue; |
| |
| // Valid values are 1, 2 and 3; 2 is the default. |
| permission = transform_params->GetIntegerFor("P", 2); |
| if (permission < 1 || permission > 3) |
| permission = 0; |
| |
| return permission; |
| } |
| |
| return permission; |
| } |