blob: 975c2522eb7d38ce2acb79f54193c142a8b67a4d [file] [log] [blame] [edit]
// 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 "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "third_party/base/stl_util.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 pdfium::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 (!pdfium::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;
}