223 lines
6.7 KiB
C++
223 lines
6.7 KiB
C++
|
|
// Copyright 2020 The PDFium Authors
|
||
|
|
// 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 <utility>
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
#include "constants/form_fields.h"
|
||
|
|
#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"
|
||
|
|
#include "third_party/base/numerics/safe_conversions.h"
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
std::vector<RetainPtr<const CPDF_Dictionary>> CollectSignatures(
|
||
|
|
CPDF_Document* doc) {
|
||
|
|
std::vector<RetainPtr<const CPDF_Dictionary>> signatures;
|
||
|
|
const CPDF_Dictionary* root = doc->GetRoot();
|
||
|
|
if (!root)
|
||
|
|
return signatures;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> acro_form = root->GetDictFor("AcroForm");
|
||
|
|
if (!acro_form)
|
||
|
|
return signatures;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Array> fields = acro_form->GetArrayFor("Fields");
|
||
|
|
if (!fields)
|
||
|
|
return signatures;
|
||
|
|
|
||
|
|
CPDF_ArrayLocker locker(std::move(fields));
|
||
|
|
for (auto& field : locker) {
|
||
|
|
RetainPtr<const CPDF_Dictionary> field_dict = field->GetDict();
|
||
|
|
if (field_dict && field_dict->GetNameFor(pdfium::form_fields::kFT) ==
|
||
|
|
pdfium::form_fields::kSig) {
|
||
|
|
signatures.push_back(std::move(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<RetainPtr<const CPDF_Dictionary>> signatures =
|
||
|
|
CollectSignatures(doc);
|
||
|
|
if (!fxcrt::IndexInBounds(signatures, index))
|
||
|
|
return nullptr;
|
||
|
|
|
||
|
|
return FPDFSignatureFromCPDFDictionary(signatures[index].Get());
|
||
|
|
}
|
||
|
|
|
||
|
|
FPDF_EXPORT unsigned long FPDF_CALLCONV
|
||
|
|
FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,
|
||
|
|
void* buffer,
|
||
|
|
unsigned long length) {
|
||
|
|
const CPDF_Dictionary* signature_dict =
|
||
|
|
CPDFDictionaryFromFPDFSignature(signature);
|
||
|
|
if (!signature_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> value_dict =
|
||
|
|
signature_dict->GetDictFor(pdfium::form_fields::kV);
|
||
|
|
if (!value_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
ByteString contents = value_dict->GetByteStringFor("Contents");
|
||
|
|
const unsigned long contents_len =
|
||
|
|
pdfium::base::checked_cast<unsigned long>(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) {
|
||
|
|
const CPDF_Dictionary* signature_dict =
|
||
|
|
CPDFDictionaryFromFPDFSignature(signature);
|
||
|
|
if (!signature_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> value_dict =
|
||
|
|
signature_dict->GetDictFor(pdfium::form_fields::kV);
|
||
|
|
if (!value_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Array> byte_range = value_dict->GetArrayFor("ByteRange");
|
||
|
|
if (!byte_range)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
const unsigned long byte_range_len =
|
||
|
|
fxcrt::CollectionSize<unsigned long>(*byte_range);
|
||
|
|
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) {
|
||
|
|
const CPDF_Dictionary* signature_dict =
|
||
|
|
CPDFDictionaryFromFPDFSignature(signature);
|
||
|
|
if (!signature_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> value_dict =
|
||
|
|
signature_dict->GetDictFor(pdfium::form_fields::kV);
|
||
|
|
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) {
|
||
|
|
const CPDF_Dictionary* signature_dict =
|
||
|
|
CPDFDictionaryFromFPDFSignature(signature);
|
||
|
|
if (!signature_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> value_dict =
|
||
|
|
signature_dict->GetDictFor(pdfium::form_fields::kV);
|
||
|
|
if (!value_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<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) {
|
||
|
|
const CPDF_Dictionary* signature_dict =
|
||
|
|
CPDFDictionaryFromFPDFSignature(signature);
|
||
|
|
if (!signature_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> value_dict =
|
||
|
|
signature_dict->GetDictFor(pdfium::form_fields::kV);
|
||
|
|
if (!value_dict)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
RetainPtr<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;
|
||
|
|
const CPDF_Dictionary* signature_dict =
|
||
|
|
CPDFDictionaryFromFPDFSignature(signature);
|
||
|
|
if (!signature_dict)
|
||
|
|
return permission;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Dictionary> value_dict =
|
||
|
|
signature_dict->GetDictFor(pdfium::form_fields::kV);
|
||
|
|
if (!value_dict)
|
||
|
|
return permission;
|
||
|
|
|
||
|
|
RetainPtr<const CPDF_Array> references = value_dict->GetArrayFor("Reference");
|
||
|
|
if (!references)
|
||
|
|
return permission;
|
||
|
|
|
||
|
|
CPDF_ArrayLocker locker(std::move(references));
|
||
|
|
for (auto& reference : locker) {
|
||
|
|
RetainPtr<const CPDF_Dictionary> reference_dict = reference->GetDict();
|
||
|
|
if (!reference_dict)
|
||
|
|
continue;
|
||
|
|
|
||
|
|
ByteString transform_method = reference_dict->GetNameFor("TransformMethod");
|
||
|
|
if (transform_method != "DocMDP")
|
||
|
|
continue;
|
||
|
|
|
||
|
|
RetainPtr<const 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;
|
||
|
|
}
|