blob: 7ce6003f96cb18728425747e11aa302cfa0d4cab [file] [log] [blame]
Jane Liu53aafa92017-07-12 19:55:02 -04001// Copyright 2017 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
Jane Liuf63e8132017-07-25 18:11:27 -04005#include <memory>
6#include <string>
7#include <vector>
8
Jane Liu53aafa92017-07-12 19:55:02 -04009#include "public/fpdf_attachment.h"
Jane Liu18ae06d2017-07-18 10:15:16 -040010#include "public/fpdfview.h"
Jane Liu53aafa92017-07-12 19:55:02 -040011#include "testing/embedder_test.h"
Lei Zhangb6992dd2019-02-05 23:30:20 +000012#include "testing/fx_string_testhelpers.h"
Lei Zhang4c64e962019-02-05 19:24:12 +000013#include "testing/utils/hash.h"
Jane Liu53aafa92017-07-12 19:55:02 -040014
Lei Zhangdf064df2017-08-31 02:33:27 -070015static constexpr char kDateKey[] = "CreationDate";
16static constexpr char kChecksumKey[] = "CheckSum";
17
Lei Zhangab41f252018-12-23 03:10:50 +000018class FPDFAttachmentEmbedderTest : public EmbedderTest {};
Jane Liu53aafa92017-07-12 19:55:02 -040019
Lei Zhangab41f252018-12-23 03:10:50 +000020TEST_F(FPDFAttachmentEmbedderTest, ExtractAttachments) {
Jane Liu53aafa92017-07-12 19:55:02 -040021 // Open a file with two attachments.
22 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
23 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
24
Jane Liu18ae06d2017-07-18 10:15:16 -040025 // Retrieve the first attachment.
26 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
27 ASSERT_TRUE(attachment);
28
Jane Liu53aafa92017-07-12 19:55:02 -040029 // Check that the name of the first attachment is correct.
Lei Zhang960e2952019-05-15 20:58:36 +000030 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
31 ASSERT_EQ(12u, length_bytes);
32 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
33 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
34 EXPECT_EQ(L"1.txt", GetPlatformWString(buf.data()));
Jane Liu18ae06d2017-07-18 10:15:16 -040035
36 // Check that the content of the first attachment is correct.
Lei Zhang960e2952019-05-15 20:58:36 +000037 length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
38 std::vector<char> content_buf(length_bytes);
39 ASSERT_EQ(
40 4u, FPDFAttachment_GetFile(attachment, content_buf.data(), length_bytes));
41 EXPECT_EQ(std::string("test"), std::string(content_buf.data(), 4));
Jane Liu18ae06d2017-07-18 10:15:16 -040042
43 // Check that a non-existent key does not exist.
Lei Zhangdf064df2017-08-31 02:33:27 -070044 EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none"));
Jane Liu18ae06d2017-07-18 10:15:16 -040045
46 // Check that the string value of a non-string dictionary entry is empty.
Lei Zhangdf064df2017-08-31 02:33:27 -070047 static constexpr char kSizeKey[] = "Size";
Jane Liu18ae06d2017-07-18 10:15:16 -040048 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Lei Zhangdf064df2017-08-31 02:33:27 -070049 FPDFAttachment_GetValueType(attachment, kSizeKey));
50 EXPECT_EQ(2u,
51 FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0));
Jane Liu18ae06d2017-07-18 10:15:16 -040052
53 // Check that the creation date of the first attachment is correct.
Lei Zhang960e2952019-05-15 20:58:36 +000054 length_bytes =
55 FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
56 ASSERT_EQ(48u, length_bytes);
57 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhangdf064df2017-08-31 02:33:27 -070058 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
Lei Zhang960e2952019-05-15 20:58:36 +000059 length_bytes));
60 EXPECT_EQ(L"D:20170712214438-07'00'", GetPlatformWString(buf.data()));
Jane Liu18ae06d2017-07-18 10:15:16 -040061
62 // Retrieve the second attachment.
63 attachment = FPDFDoc_GetAttachment(document(), 1);
64 ASSERT_TRUE(attachment);
65
66 // Retrieve the second attachment file.
Lei Zhang960e2952019-05-15 20:58:36 +000067 length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
68 content_buf.clear();
69 content_buf.resize(length_bytes);
70 ASSERT_EQ(5869u, FPDFAttachment_GetFile(attachment, content_buf.data(),
71 length_bytes));
Jane Liu18ae06d2017-07-18 10:15:16 -040072
73 // Check that the calculated checksum of the file data matches expectation.
74 const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
75 const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
Lei Zhang960e2952019-05-15 20:58:36 +000076 const std::string generated_checksum = GenerateMD5Base16(
77 reinterpret_cast<uint8_t*>(content_buf.data()), length_bytes);
Jane Liu18ae06d2017-07-18 10:15:16 -040078 EXPECT_EQ(kCheckSum, generated_checksum);
79
80 // Check that the stored checksum matches expectation.
Lei Zhang960e2952019-05-15 20:58:36 +000081 length_bytes =
82 FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
83 ASSERT_EQ(70u, length_bytes);
84 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhangdf064df2017-08-31 02:33:27 -070085 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Lei Zhang960e2952019-05-15 20:58:36 +000086 buf.data(), length_bytes));
87 EXPECT_EQ(kCheckSumW, GetPlatformWString(buf.data()));
Jane Liu53aafa92017-07-12 19:55:02 -040088}
Jane Liu54a42142017-07-24 16:40:54 -040089
Lei Zhangab41f252018-12-23 03:10:50 +000090TEST_F(FPDFAttachmentEmbedderTest, AddAttachments) {
Jane Liu54a42142017-07-24 16:40:54 -040091 // Open a file with two attachments.
92 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
93 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
94
95 // Check that adding an attachment with an empty name would fail.
96 EXPECT_FALSE(FPDFDoc_AddAttachment(document(), nullptr));
97
98 // Add an attachment to the beginning of the embedded file list.
Lei Zhangf0f67682019-04-08 17:03:21 +000099 ScopedFPDFWideString file_name = GetFPDFWideString(L"0.txt");
Jane Liu54a42142017-07-24 16:40:54 -0400100 FPDF_ATTACHMENT attachment =
101 FPDFDoc_AddAttachment(document(), file_name.get());
102
103 // Check that writing to a file with nullptr but non-zero bytes would fail.
104 EXPECT_FALSE(FPDFAttachment_SetFile(attachment, document(), nullptr, 10));
105
106 // Set the new attachment's file.
107 constexpr char kContents1[] = "Hello!";
108 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
109 strlen(kContents1)));
110
111 // Verify the name of the new attachment (i.e. the first attachment).
112 attachment = FPDFDoc_GetAttachment(document(), 0);
113 ASSERT_TRUE(attachment);
Lei Zhang960e2952019-05-15 20:58:36 +0000114 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
115 ASSERT_EQ(12u, length_bytes);
116 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
117 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
118 EXPECT_EQ(L"0.txt", GetPlatformWString(buf.data()));
Jane Liu54a42142017-07-24 16:40:54 -0400119
120 // Verify the content of the new attachment (i.e. the first attachment).
Lei Zhang960e2952019-05-15 20:58:36 +0000121 length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
122 std::vector<char> content_buf(length_bytes);
123 ASSERT_EQ(
124 6u, FPDFAttachment_GetFile(attachment, content_buf.data(), length_bytes));
125 EXPECT_EQ(std::string(kContents1), std::string(content_buf.data(), 6));
Jane Liu54a42142017-07-24 16:40:54 -0400126
127 // Add an attachment to the end of the embedded file list and set its file.
128 file_name = GetFPDFWideString(L"z.txt");
129 attachment = FPDFDoc_AddAttachment(document(), file_name.get());
130 constexpr char kContents2[] = "World!";
131 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
132 strlen(kContents2)));
133 EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document()));
134
135 // Verify the name of the new attachment (i.e. the fourth attachment).
136 attachment = FPDFDoc_GetAttachment(document(), 3);
137 ASSERT_TRUE(attachment);
Lei Zhang960e2952019-05-15 20:58:36 +0000138 length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
139 ASSERT_EQ(12u, length_bytes);
140 buf = GetFPDFWideStringBuffer(length_bytes);
141 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
142 EXPECT_EQ(L"z.txt", GetPlatformWString(buf.data()));
Jane Liu54a42142017-07-24 16:40:54 -0400143
144 // Verify the content of the new attachment (i.e. the fourth attachment).
Lei Zhang960e2952019-05-15 20:58:36 +0000145 length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
146 content_buf.clear();
147 content_buf.resize(length_bytes);
148 ASSERT_EQ(
149 6u, FPDFAttachment_GetFile(attachment, content_buf.data(), length_bytes));
150 EXPECT_EQ(std::string(kContents2), std::string(content_buf.data(), 6));
Jane Liu54a42142017-07-24 16:40:54 -0400151}
152
Lei Zhangab41f252018-12-23 03:10:50 +0000153TEST_F(FPDFAttachmentEmbedderTest, AddAttachmentsWithParams) {
Jane Liu54a42142017-07-24 16:40:54 -0400154 // Open a file with two attachments.
155 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
156 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
157
158 // Add an attachment to the embedded file list.
Lei Zhangf0f67682019-04-08 17:03:21 +0000159 ScopedFPDFWideString file_name = GetFPDFWideString(L"5.txt");
Jane Liu54a42142017-07-24 16:40:54 -0400160 FPDF_ATTACHMENT attachment =
161 FPDFDoc_AddAttachment(document(), file_name.get());
162 constexpr char kContents[] = "Hello World!";
163 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents,
164 strlen(kContents)));
165
166 // Set the date to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400167 constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
Lei Zhangf0f67682019-04-08 17:03:21 +0000168 ScopedFPDFWideString ws_date = GetFPDFWideString(kDateW);
Jane Liu54a42142017-07-24 16:40:54 -0400169 EXPECT_TRUE(
Lei Zhangdf064df2017-08-31 02:33:27 -0700170 FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get()));
Jane Liu54a42142017-07-24 16:40:54 -0400171
172 // Set the checksum to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400173 constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
Lei Zhangf0f67682019-04-08 17:03:21 +0000174 ScopedFPDFWideString ws_checksum = GetFPDFWideString(kCheckSumW);
Lei Zhangdf064df2017-08-31 02:33:27 -0700175 EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400176 ws_checksum.get()));
177
178 // Verify the name of the new attachment (i.e. the second attachment).
179 attachment = FPDFDoc_GetAttachment(document(), 1);
180 ASSERT_TRUE(attachment);
Lei Zhang960e2952019-05-15 20:58:36 +0000181 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
182 ASSERT_EQ(12u, length_bytes);
183 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
184 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
185 EXPECT_EQ(L"5.txt", GetPlatformWString(buf.data()));
Jane Liu54a42142017-07-24 16:40:54 -0400186
187 // Verify the content of the new attachment.
Lei Zhang960e2952019-05-15 20:58:36 +0000188 length_bytes = FPDFAttachment_GetFile(attachment, nullptr, 0);
189 std::vector<char> content_buf(length_bytes);
190 ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, content_buf.data(),
191 length_bytes));
192 EXPECT_EQ(std::string(kContents), std::string(content_buf.data(), 12));
Jane Liu54a42142017-07-24 16:40:54 -0400193
194 // Verify the creation date of the new attachment.
Lei Zhang960e2952019-05-15 20:58:36 +0000195 length_bytes =
196 FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
197 ASSERT_EQ(48u, length_bytes);
198 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhangdf064df2017-08-31 02:33:27 -0700199 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
Lei Zhang960e2952019-05-15 20:58:36 +0000200 length_bytes));
201 EXPECT_EQ(kDateW, GetPlatformWString(buf.data()));
Jane Liu54a42142017-07-24 16:40:54 -0400202
203 // Verify the checksum of the new attachment.
Lei Zhang960e2952019-05-15 20:58:36 +0000204 length_bytes =
205 FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
206 ASSERT_EQ(70u, length_bytes);
207 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhangdf064df2017-08-31 02:33:27 -0700208 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Lei Zhang960e2952019-05-15 20:58:36 +0000209 buf.data(), length_bytes));
210 EXPECT_EQ(kCheckSumW, GetPlatformWString(buf.data()));
Jane Liu54a42142017-07-24 16:40:54 -0400211
212 // Overwrite the existing file with empty content, and check that the checksum
213 // gets updated to the correct value.
214 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
215 EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
Lei Zhang960e2952019-05-15 20:58:36 +0000216 length_bytes =
217 FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
218 ASSERT_EQ(70u, length_bytes);
219 buf = GetFPDFWideStringBuffer(length_bytes);
Lei Zhangdf064df2017-08-31 02:33:27 -0700220 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Lei Zhang960e2952019-05-15 20:58:36 +0000221 buf.data(), length_bytes));
Jane Liu54a42142017-07-24 16:40:54 -0400222 EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
Lei Zhang960e2952019-05-15 20:58:36 +0000223 GetPlatformWString(buf.data()));
Jane Liuf63e8132017-07-25 18:11:27 -0400224}
225
Lei Zhangab41f252018-12-23 03:10:50 +0000226TEST_F(FPDFAttachmentEmbedderTest, DeleteAttachment) {
Jane Liuf63e8132017-07-25 18:11:27 -0400227 // Open a file with two attachments.
228 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
229 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
230
231 // Verify the name of the first attachment.
232 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
Lei Zhang960e2952019-05-15 20:58:36 +0000233 unsigned long length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
234 ASSERT_EQ(12u, length_bytes);
235 std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(length_bytes);
236 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
237 EXPECT_EQ(L"1.txt", GetPlatformWString(buf.data()));
Jane Liuf63e8132017-07-25 18:11:27 -0400238
239 // Delete the first attachment.
240 EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
241 EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
242
243 // Verify the name of the new first attachment.
244 attachment = FPDFDoc_GetAttachment(document(), 0);
Lei Zhang960e2952019-05-15 20:58:36 +0000245 length_bytes = FPDFAttachment_GetName(attachment, nullptr, 0);
246 ASSERT_EQ(26u, length_bytes);
247 buf = GetFPDFWideStringBuffer(length_bytes);
248 EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), length_bytes));
249 EXPECT_EQ(L"attached.pdf", GetPlatformWString(buf.data()));
Jane Liuf63e8132017-07-25 18:11:27 -0400250}