Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fpdf_attachment_embeddertest.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
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 <string>
6#include <vector>
7
8#include "public/fpdf_attachment.h"
9#include "public/fpdfview.h"
10#include "testing/embedder_test.h"
11#include "testing/fx_string_testhelpers.h"
12#include "testing/gmock/include/gmock/gmock.h"
13#include "testing/utils/hash.h"
14
15static constexpr char kDateKey[] = "CreationDate";
16static constexpr char kChecksumKey[] = "CheckSum";
17
19
21 // Open a file with two attachments.
22 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
23 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
24
25 // Try to retrieve attachments at bad indices.
26 EXPECT_FALSE(FPDFDoc_GetAttachment(document(), -1));
27 EXPECT_FALSE(FPDFDoc_GetAttachment(document(), 2));
28
29 // Retrieve the first attachment.
30 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
31 ASSERT_TRUE(attachment);
32
33 // Check that the name of the first attachment is correct.
34 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
35 ASSERT_EQ(12u, length_bytes);
36 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
37 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
38 EXPECT_EQ(L"1.txt", GetPlatformWString(buf.data()));
39
40 // Check some unsuccessful cases of FPDFAttachment_GetFile.
41 EXPECT_FALSE(FPDFAttachment_GetFile(attachment, nullptr, 0, nullptr));
42 EXPECT_FALSE(FPDFAttachment_GetFile(nullptr, nullptr, 0, &length_bytes));
43
44 // Check that the content of the first attachment is correct.
45 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
46 std::vector<uint8_t> content_buf(length_bytes);
47 unsigned long actual_length_bytes;
48 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
49 length_bytes, &actual_length_bytes));
50 ASSERT_THAT(content_buf, testing::ElementsAre('t', 'e', 's', 't'));
51
52 // Check that a non-existent key does not exist.
53 EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none"));
54
55 // Check that the string value of a non-string dictionary entry is empty.
56 static constexpr char kSizeKey[] = "Size";
57 EXPECT_EQ(FPDF_OBJECT_NUMBER,
58 FPDFAttachment_GetValueType(attachment, kSizeKey));
59 EXPECT_EQ(2u,
60 FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0));
61
62 // Check that the creation date of the first attachment is correct.
63 length_bytes =
65 ASSERT_EQ(48u, length_bytes);
66 buf = GetFPDFWideStringBuffer(length_bytes);
67 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
68 length_bytes));
69 EXPECT_EQ(L"D:20170712214438-07'00'", GetPlatformWString(buf.data()));
70
71 // Retrieve the second attachment.
72 attachment = FPDFDoc_GetAttachment(document(), 1);
73 ASSERT_TRUE(attachment);
74
75 // Retrieve the second attachment file.
76 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
77 content_buf.clear();
78 content_buf.resize(length_bytes);
79 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
80 length_bytes, &actual_length_bytes));
81 ASSERT_EQ(5869u, actual_length_bytes);
82
83 // Check that the calculated checksum of the file data matches expectation.
84 const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
85 const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
86 const std::string generated_checksum = GenerateMD5Base16(content_buf);
87 EXPECT_EQ(kCheckSum, generated_checksum);
88
89 // Check that the stored checksum matches expectation.
90 length_bytes =
92 ASSERT_EQ(70u, length_bytes);
93 buf = GetFPDFWideStringBuffer(length_bytes);
94 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
95 buf.data(), length_bytes));
96 EXPECT_EQ(kCheckSumW, GetPlatformWString(buf.data()));
97}
98
100 // Open a file with no attachments.
101 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
102 EXPECT_EQ(0, FPDFDoc_GetAttachmentCount(document()));
103
104 // Try to retrieve attachments at bad indices.
105 EXPECT_FALSE(FPDFDoc_GetAttachment(document(), -1));
106 EXPECT_FALSE(FPDFDoc_GetAttachment(document(), 0));
107}
108
110 // Open a file with an attachment that is missing the embedded file (/EF).
111 ASSERT_TRUE(OpenDocument("embedded_attachments_invalid_data.pdf"));
112 ASSERT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
113
114 // Retrieve the first attachment.
115 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
116 ASSERT_TRUE(attachment);
117
118 // Check that the name of the attachment is correct.
119 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
120 ASSERT_EQ(12u, length_bytes);
121 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
122 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
123 EXPECT_EQ("1.txt", GetPlatformString(buf.data()));
124
125 // Check that is is not possible to retrieve the file data.
126 EXPECT_FALSE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
127
128 // Check that the attachment can be deleted.
129 EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
130 EXPECT_EQ(0, FPDFDoc_GetAttachmentCount(document()));
131}
132
134 // Open a file with two attachments.
135 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
136 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
137
138 // Check that adding an attachment with an empty name would fail.
139 EXPECT_FALSE(FPDFDoc_AddAttachment(document(), nullptr));
140
141 // Add an attachment to the beginning of the embedded file list.
142 ScopedFPDFWideString file_name = GetFPDFWideString(L"0.txt");
143 FPDF_ATTACHMENT attachment =
144 FPDFDoc_AddAttachment(document(), file_name.get());
145 ASSERT_TRUE(attachment);
146
147 // Check that writing to a file with nullptr but non-zero bytes would fail.
148 EXPECT_FALSE(FPDFAttachment_SetFile(attachment, document(), nullptr, 10));
149
150 // Set the new attachment's file.
151 constexpr char kContents1[] = "Hello!";
152 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
153 strlen(kContents1)));
154 EXPECT_EQ(3, FPDFDoc_GetAttachmentCount(document()));
155
156 // Verify the name of the new attachment (i.e. the first attachment).
157 attachment = FPDFDoc_GetAttachment(document(), 0);
158 ASSERT_TRUE(attachment);
159 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
160 ASSERT_EQ(12u, length_bytes);
161 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
162 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
163 EXPECT_EQ(L"0.txt", GetPlatformWString(buf.data()));
164
165 // Verify the content of the new attachment (i.e. the first attachment).
166 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
167 std::vector<char> content_buf(length_bytes);
168 unsigned long actual_length_bytes;
169 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
170 length_bytes, &actual_length_bytes));
171 ASSERT_EQ(6u, actual_length_bytes);
172 EXPECT_EQ(std::string(kContents1), std::string(content_buf.data(), 6));
173
174 // Add an attachment to the end of the embedded file list and set its file.
175 file_name = GetFPDFWideString(L"z.txt");
176 attachment = FPDFDoc_AddAttachment(document(), file_name.get());
177 ASSERT_TRUE(attachment);
178 constexpr char kContents2[] = "World!";
179 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
180 strlen(kContents2)));
181 EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document()));
182
183 // Verify the name of the new attachment (i.e. the fourth attachment).
184 attachment = FPDFDoc_GetAttachment(document(), 3);
185 ASSERT_TRUE(attachment);
186 length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
187 ASSERT_EQ(12u, length_bytes);
188 buf = GetFPDFWideStringBuffer(length_bytes);
189 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
190 EXPECT_EQ(L"z.txt", GetPlatformWString(buf.data()));
191
192 // Verify the content of the new attachment (i.e. the fourth attachment).
193 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
194 content_buf.clear();
195 content_buf.resize(length_bytes);
196 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
197 length_bytes, &actual_length_bytes));
198 ASSERT_EQ(6u, actual_length_bytes);
199 EXPECT_EQ(std::string(kContents2), std::string(content_buf.data(), 6));
200}
201
203 // Open a file with two attachments.
204 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
205 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
206
207 // Add an attachment to the embedded file list.
208 ScopedFPDFWideString file_name = GetFPDFWideString(L"5.txt");
209 FPDF_ATTACHMENT attachment =
210 FPDFDoc_AddAttachment(document(), file_name.get());
211 ASSERT_TRUE(attachment);
212 constexpr char kContents[] = "Hello World!";
213 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents,
214 strlen(kContents)));
215
216 // Set the date to be an arbitrary value.
217 constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
218 ScopedFPDFWideString ws_date = GetFPDFWideString(kDateW);
219 EXPECT_TRUE(
220 FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get()));
221
222 // Set the checksum to be an arbitrary value.
223 constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
224 ScopedFPDFWideString ws_checksum = GetFPDFWideString(kCheckSumW);
225 EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey,
226 ws_checksum.get()));
227
228 // Verify the name of the new attachment (i.e. the second attachment).
229 attachment = FPDFDoc_GetAttachment(document(), 1);
230 ASSERT_TRUE(attachment);
231 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
232 ASSERT_EQ(12u, length_bytes);
233 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
234 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
235 EXPECT_EQ(L"5.txt", GetPlatformWString(buf.data()));
236
237 // Verify the content of the new attachment.
238 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
239 std::vector<char> content_buf(length_bytes);
240 unsigned long actual_length_bytes;
241 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
242 length_bytes, &actual_length_bytes));
243 ASSERT_EQ(12u, actual_length_bytes);
244 EXPECT_EQ(std::string(kContents), std::string(content_buf.data(), 12));
245
246 // Verify the creation date of the new attachment.
247 length_bytes =
249 ASSERT_EQ(48u, length_bytes);
250 buf = GetFPDFWideStringBuffer(length_bytes);
251 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
252 length_bytes));
253 EXPECT_EQ(kDateW, GetPlatformWString(buf.data()));
254
255 // Verify the checksum of the new attachment.
256 length_bytes =
258 ASSERT_EQ(70u, length_bytes);
259 buf = GetFPDFWideStringBuffer(length_bytes);
260 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
261 buf.data(), length_bytes));
262 EXPECT_EQ(kCheckSumW, GetPlatformWString(buf.data()));
263
264 // Overwrite the existing file with empty content, and check that the checksum
265 // gets updated to the correct value.
266 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
267 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
268 EXPECT_EQ(0u, length_bytes);
269 length_bytes =
271 ASSERT_EQ(70u, length_bytes);
272 buf = GetFPDFWideStringBuffer(length_bytes);
273 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
274 buf.data(), length_bytes));
275 EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
276 GetPlatformWString(buf.data()));
277}
278
280 // Open a file with no attachments.
281 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
282 EXPECT_EQ(0, FPDFDoc_GetAttachmentCount(document()));
283
284 // Add an attachment to the beginning of the embedded file list.
285 ScopedFPDFWideString file_name = GetFPDFWideString(L"0.txt");
286 FPDF_ATTACHMENT attachment =
287 FPDFDoc_AddAttachment(document(), file_name.get());
288 ASSERT_TRUE(attachment);
289
290 // Set the new attachment's file.
291 constexpr char kContents1[] = "Hello!";
292 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
293 strlen(kContents1)));
294 EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
295
296 // Verify the name of the new attachment (i.e. the first attachment).
297 attachment = FPDFDoc_GetAttachment(document(), 0);
298 ASSERT_TRUE(attachment);
299 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
300 ASSERT_EQ(12u, length_bytes);
301 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
302 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
303 EXPECT_EQ(L"0.txt", GetPlatformWString(buf.data()));
304
305 // Verify the content of the new attachment (i.e. the first attachment).
306 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
307 std::vector<char> content_buf(length_bytes);
308 unsigned long actual_length_bytes;
309 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
310 length_bytes, &actual_length_bytes));
311 ASSERT_EQ(6u, actual_length_bytes);
312 EXPECT_EQ(std::string(kContents1), std::string(content_buf.data(), 6));
313
314 // Add an attachment to the end of the embedded file list and set its file.
315 file_name = GetFPDFWideString(L"z.txt");
316 attachment = FPDFDoc_AddAttachment(document(), file_name.get());
317 ASSERT_TRUE(attachment);
318 constexpr char kContents2[] = "World!";
319 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
320 strlen(kContents2)));
321 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
322
323 // Verify the name of the new attachment (i.e. the second attachment).
324 attachment = FPDFDoc_GetAttachment(document(), 1);
325 ASSERT_TRUE(attachment);
326 length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
327 ASSERT_EQ(12u, length_bytes);
328 buf = GetFPDFWideStringBuffer(length_bytes);
329 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
330 EXPECT_EQ(L"z.txt", GetPlatformWString(buf.data()));
331
332 // Verify the content of the new attachment (i.e. the second attachment).
333 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, nullptr, 0, &length_bytes));
334 content_buf.clear();
335 content_buf.resize(length_bytes);
336 ASSERT_TRUE(FPDFAttachment_GetFile(attachment, content_buf.data(),
337 length_bytes, &actual_length_bytes));
338 ASSERT_EQ(6u, actual_length_bytes);
339 EXPECT_EQ(std::string(kContents2), std::string(content_buf.data(), 6));
340}
341
343 // Open a file with two attachments.
344 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
345 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
346
347 // Verify the name of the first attachment.
348 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
349 ASSERT_TRUE(attachment);
350 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
351 ASSERT_EQ(12u, length_bytes);
352 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
353 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
354 EXPECT_EQ(L"1.txt", GetPlatformWString(buf.data()));
355
356 // Delete the first attachment.
357 EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
358 EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
359
360 // Verify the name of the new first attachment.
361 attachment = FPDFDoc_GetAttachment(document(), 0);
362 ASSERT_TRUE(attachment);
363 length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
364 ASSERT_EQ(26u, length_bytes);
365 buf = GetFPDFWideStringBuffer(length_bytes);
366 EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
367 EXPECT_EQ(L"attached.pdf", GetPlatformWString(buf.data()));
368}
FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV FPDFAttachment_GetValueType(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key, FPDF_WCHAR *buffer, unsigned long buflen)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAttachment_GetName(FPDF_ATTACHMENT attachment, FPDF_WCHAR *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAttachment_GetFile(FPDF_ATTACHMENT attachment, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFAttachment_HasKey(FPDF_ATTACHMENT attachment, FPDF_BYTESTRING key)
static constexpr char kDateKey[]
TEST_F(FPDFAttachmentEmbedderTest, ExtractAttachments)
static constexpr char kChecksumKey[]
#define FPDF_OBJECT_NUMBER
Definition fpdfview.h:38