1 // Copyright 2020 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "public/fpdf_signature.h"
6
7 #include "core/fpdfapi/parser/cpdf_array.h"
8 #include "core/fpdfapi/parser/cpdf_dictionary.h"
9 #include "core/fpdfapi/parser/cpdf_document.h"
10 #include "fpdfsdk/cpdfsdk_helpers.h"
11 #include "third_party/base/stl_util.h"
12
13 namespace {
14
CollectSignatures(CPDF_Document * doc)15 std::vector<CPDF_Dictionary*> CollectSignatures(CPDF_Document* doc) {
16 std::vector<CPDF_Dictionary*> signatures;
17 CPDF_Dictionary* root = doc->GetRoot();
18 if (!root)
19 return signatures;
20
21 const CPDF_Dictionary* acro_form = root->GetDictFor("AcroForm");
22 if (!acro_form)
23 return signatures;
24
25 const CPDF_Array* fields = acro_form->GetArrayFor("Fields");
26 if (!fields)
27 return signatures;
28
29 CPDF_ArrayLocker locker(fields);
30 for (auto& field : locker) {
31 CPDF_Dictionary* field_dict = field->GetDict();
32 if (field_dict && field_dict->GetNameFor("FT") == "Sig")
33 signatures.push_back(field_dict);
34 }
35 return signatures;
36 }
37
38 } // namespace
39
FPDF_GetSignatureCount(FPDF_DOCUMENT document)40 FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document) {
41 auto* doc = CPDFDocumentFromFPDFDocument(document);
42 if (!doc)
43 return -1;
44
45 return pdfium::CollectionSize<int>(CollectSignatures(doc));
46 }
47
48 FPDF_EXPORT FPDF_SIGNATURE FPDF_CALLCONV
FPDF_GetSignatureObject(FPDF_DOCUMENT document,int index)49 FPDF_GetSignatureObject(FPDF_DOCUMENT document, int index) {
50 auto* doc = CPDFDocumentFromFPDFDocument(document);
51 if (!doc)
52 return nullptr;
53
54 std::vector<CPDF_Dictionary*> signatures = CollectSignatures(doc);
55 if (!pdfium::IndexInBounds(signatures, index))
56 return nullptr;
57
58 return FPDFSignatureFromCPDFDictionary(signatures[index]);
59 }
60
61 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,void * buffer,unsigned long length)62 FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,
63 void* buffer,
64 unsigned long length) {
65 CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
66 if (!signature_dict)
67 return 0;
68
69 CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
70 if (!value_dict)
71 return 0;
72
73 ByteString contents = value_dict->GetStringFor("Contents");
74 unsigned long contents_len = contents.GetLength();
75 if (buffer && length >= contents_len)
76 memcpy(buffer, contents.c_str(), contents_len);
77
78 return contents_len;
79 }
80
81 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature,int * buffer,unsigned long length)82 FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature,
83 int* buffer,
84 unsigned long length) {
85 CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
86 if (!signature_dict)
87 return 0;
88
89 CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
90 if (!value_dict)
91 return 0;
92
93 const CPDF_Array* byte_range = value_dict->GetArrayFor("ByteRange");
94 if (!byte_range)
95 return 0;
96
97 unsigned long byte_range_len = byte_range->size();
98 if (buffer && length >= byte_range_len) {
99 for (size_t i = 0; i < byte_range_len; ++i)
100 buffer[i] = byte_range->GetIntegerAt(i);
101 }
102
103 return byte_range_len;
104 }
105
106 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature,char * buffer,unsigned long length)107 FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature,
108 char* buffer,
109 unsigned long length) {
110 CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
111 if (!signature_dict)
112 return 0;
113
114 CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
115 if (!value_dict || !value_dict->KeyExist("SubFilter"))
116 return 0;
117
118 ByteString sub_filter = value_dict->GetNameFor("SubFilter");
119 return NulTerminateMaybeCopyAndReturnLength(sub_filter, buffer, length);
120 }
121
122 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature,void * buffer,unsigned long length)123 FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature,
124 void* buffer,
125 unsigned long length) {
126 CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
127 if (!signature_dict)
128 return 0;
129
130 CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
131 if (!value_dict)
132 return 0;
133
134 const CPDF_Object* obj = value_dict->GetObjectFor("Reason");
135 if (!obj || !obj->IsString())
136 return 0;
137
138 return Utf16EncodeMaybeCopyAndReturnLength(obj->GetUnicodeText(), buffer,
139 length);
140 }
141
142 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature,char * buffer,unsigned long length)143 FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature,
144 char* buffer,
145 unsigned long length) {
146 CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
147 if (!signature_dict)
148 return 0;
149
150 CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
151 if (!value_dict)
152 return 0;
153
154 const CPDF_Object* obj = value_dict->GetObjectFor("M");
155 if (!obj || !obj->IsString())
156 return 0;
157
158 return NulTerminateMaybeCopyAndReturnLength(obj->GetString(), buffer, length);
159 }
160
161 FPDF_EXPORT unsigned int FPDF_CALLCONV
FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature)162 FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature) {
163 int permission = 0;
164 CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
165 if (!signature_dict)
166 return permission;
167
168 CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
169 if (!value_dict)
170 return permission;
171
172 CPDF_Array* references = value_dict->GetArrayFor("Reference");
173 if (!references)
174 return permission;
175
176 CPDF_ArrayLocker locker(references);
177 for (auto& reference : locker) {
178 CPDF_Dictionary* reference_dict = reference->GetDict();
179 if (!reference_dict)
180 continue;
181
182 ByteString transform_method = reference_dict->GetNameFor("TransformMethod");
183 if (transform_method != "DocMDP")
184 continue;
185
186 CPDF_Dictionary* transform_params =
187 reference_dict->GetDictFor("TransformParams");
188 if (!transform_params)
189 continue;
190
191 // Valid values are 1, 2 and 3; 2 is the default.
192 permission = transform_params->GetIntegerFor("P", 2);
193 if (permission < 1 || permission > 3)
194 permission = 0;
195
196 return permission;
197 }
198
199 return permission;
200 }
201