blob: 59508ee05b54fd19ca05b1aa9b3e52d714964578 [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.
Jane Liu18ae06d2017-07-18 10:15:16 -040030 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
Jane Liu53aafa92017-07-12 19:55:02 -040031 std::vector<char> buf(len);
Jane Liu18ae06d2017-07-18 10:15:16 -040032 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
Jane Liu53aafa92017-07-12 19:55:02 -040033 EXPECT_STREQ(L"1.txt",
34 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
35 .c_str());
Jane Liu18ae06d2017-07-18 10:15:16 -040036
37 // Check that the content of the first attachment is correct.
38 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
39 buf.clear();
40 buf.resize(len);
41 ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len));
42 EXPECT_EQ(std::string("test"), std::string(buf.data(), 4));
43
44 // Check that a non-existent key does not exist.
Lei Zhangdf064df2017-08-31 02:33:27 -070045 EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none"));
Jane Liu18ae06d2017-07-18 10:15:16 -040046
47 // Check that the string value of a non-string dictionary entry is empty.
Lei Zhangdf064df2017-08-31 02:33:27 -070048 static constexpr char kSizeKey[] = "Size";
Jane Liu18ae06d2017-07-18 10:15:16 -040049 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Lei Zhangdf064df2017-08-31 02:33:27 -070050 FPDFAttachment_GetValueType(attachment, kSizeKey));
51 EXPECT_EQ(2u,
52 FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0));
Jane Liu18ae06d2017-07-18 10:15:16 -040053
54 // Check that the creation date of the first attachment is correct.
Lei Zhangdf064df2017-08-31 02:33:27 -070055 len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
Jane Liu18ae06d2017-07-18 10:15:16 -040056 buf.clear();
57 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -070058 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
59 len));
Jane Liu18ae06d2017-07-18 10:15:16 -040060 EXPECT_STREQ(L"D:20170712214438-07'00'",
61 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
62 .c_str());
63
64 // Retrieve the second attachment.
65 attachment = FPDFDoc_GetAttachment(document(), 1);
66 ASSERT_TRUE(attachment);
67
68 // Retrieve the second attachment file.
69 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
70 buf.clear();
71 buf.resize(len);
72 EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len));
73
74 // Check that the calculated checksum of the file data matches expectation.
75 const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
76 const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
77 const std::string generated_checksum =
78 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len);
79 EXPECT_EQ(kCheckSum, generated_checksum);
80
81 // Check that the stored checksum matches expectation.
Lei Zhangdf064df2017-08-31 02:33:27 -070082 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu18ae06d2017-07-18 10:15:16 -040083 buf.clear();
84 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -070085 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu18ae06d2017-07-18 10:15:16 -040086 buf.data(), len));
87 EXPECT_EQ(kCheckSumW,
88 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
Jane Liu53aafa92017-07-12 19:55:02 -040089}
Jane Liu54a42142017-07-24 16:40:54 -040090
Lei Zhangab41f252018-12-23 03:10:50 +000091TEST_F(FPDFAttachmentEmbedderTest, AddAttachments) {
Jane Liu54a42142017-07-24 16:40:54 -040092 // Open a file with two attachments.
93 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
94 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
95
96 // Check that adding an attachment with an empty name would fail.
97 EXPECT_FALSE(FPDFDoc_AddAttachment(document(), nullptr));
98
99 // Add an attachment to the beginning of the embedded file list.
Lei Zhangf0f67682019-04-08 17:03:21 +0000100 ScopedFPDFWideString file_name = GetFPDFWideString(L"0.txt");
Jane Liu54a42142017-07-24 16:40:54 -0400101 FPDF_ATTACHMENT attachment =
102 FPDFDoc_AddAttachment(document(), file_name.get());
103
104 // Check that writing to a file with nullptr but non-zero bytes would fail.
105 EXPECT_FALSE(FPDFAttachment_SetFile(attachment, document(), nullptr, 10));
106
107 // Set the new attachment's file.
108 constexpr char kContents1[] = "Hello!";
109 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents1,
110 strlen(kContents1)));
111
112 // Verify the name of the new attachment (i.e. the first attachment).
113 attachment = FPDFDoc_GetAttachment(document(), 0);
114 ASSERT_TRUE(attachment);
115 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
116 std::vector<char> buf(len);
117 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
118 EXPECT_STREQ(L"0.txt",
119 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
120 .c_str());
121
122 // Verify the content of the new attachment (i.e. the first attachment).
123 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
124 buf.clear();
125 buf.resize(len);
126 ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
127 EXPECT_EQ(std::string(kContents1), std::string(buf.data(), 6));
128
129 // Add an attachment to the end of the embedded file list and set its file.
130 file_name = GetFPDFWideString(L"z.txt");
131 attachment = FPDFDoc_AddAttachment(document(), file_name.get());
132 constexpr char kContents2[] = "World!";
133 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
134 strlen(kContents2)));
135 EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document()));
136
137 // Verify the name of the new attachment (i.e. the fourth attachment).
138 attachment = FPDFDoc_GetAttachment(document(), 3);
139 ASSERT_TRUE(attachment);
140 len = FPDFAttachment_GetName(attachment, nullptr, 0);
141 buf.clear();
142 buf.resize(len);
143 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
144 EXPECT_STREQ(L"z.txt",
145 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
146 .c_str());
147
148 // Verify the content of the new attachment (i.e. the fourth attachment).
149 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
150 buf.clear();
151 buf.resize(len);
152 ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
153 EXPECT_EQ(std::string(kContents2), std::string(buf.data(), 6));
154}
155
Lei Zhangab41f252018-12-23 03:10:50 +0000156TEST_F(FPDFAttachmentEmbedderTest, AddAttachmentsWithParams) {
Jane Liu54a42142017-07-24 16:40:54 -0400157 // Open a file with two attachments.
158 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
159 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
160
161 // Add an attachment to the embedded file list.
Lei Zhangf0f67682019-04-08 17:03:21 +0000162 ScopedFPDFWideString file_name = GetFPDFWideString(L"5.txt");
Jane Liu54a42142017-07-24 16:40:54 -0400163 FPDF_ATTACHMENT attachment =
164 FPDFDoc_AddAttachment(document(), file_name.get());
165 constexpr char kContents[] = "Hello World!";
166 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents,
167 strlen(kContents)));
168
169 // Set the date to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400170 constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
Lei Zhangf0f67682019-04-08 17:03:21 +0000171 ScopedFPDFWideString ws_date = GetFPDFWideString(kDateW);
Jane Liu54a42142017-07-24 16:40:54 -0400172 EXPECT_TRUE(
Lei Zhangdf064df2017-08-31 02:33:27 -0700173 FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get()));
Jane Liu54a42142017-07-24 16:40:54 -0400174
175 // Set the checksum to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400176 constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
Lei Zhangf0f67682019-04-08 17:03:21 +0000177 ScopedFPDFWideString ws_checksum = GetFPDFWideString(kCheckSumW);
Lei Zhangdf064df2017-08-31 02:33:27 -0700178 EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400179 ws_checksum.get()));
180
181 // Verify the name of the new attachment (i.e. the second attachment).
182 attachment = FPDFDoc_GetAttachment(document(), 1);
183 ASSERT_TRUE(attachment);
184 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
185 std::vector<char> buf(len);
186 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
187 EXPECT_STREQ(L"5.txt",
188 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
189 .c_str());
190
191 // Verify the content of the new attachment.
192 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
193 buf.clear();
194 buf.resize(len);
195 ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len));
196 EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12));
197
198 // Verify the creation date of the new attachment.
Lei Zhangdf064df2017-08-31 02:33:27 -0700199 len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400200 buf.clear();
201 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700202 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
203 len));
Jane Liu54a42142017-07-24 16:40:54 -0400204 EXPECT_STREQ(kDateW,
205 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
206 .c_str());
207
208 // Verify the checksum of the new attachment.
Lei Zhangdf064df2017-08-31 02:33:27 -0700209 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400210 buf.clear();
211 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700212 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400213 buf.data(), len));
214 EXPECT_STREQ(kCheckSumW,
215 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
216 .c_str());
217
218 // Overwrite the existing file with empty content, and check that the checksum
219 // gets updated to the correct value.
220 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
221 EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
Lei Zhangdf064df2017-08-31 02:33:27 -0700222 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400223 buf.clear();
224 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700225 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400226 buf.data(), len));
227 EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
228 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
Jane Liuf63e8132017-07-25 18:11:27 -0400229}
230
Lei Zhangab41f252018-12-23 03:10:50 +0000231TEST_F(FPDFAttachmentEmbedderTest, DeleteAttachment) {
Jane Liuf63e8132017-07-25 18:11:27 -0400232 // Open a file with two attachments.
233 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
234 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
235
236 // Verify the name of the first attachment.
237 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
238 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
239 std::vector<char> buf(len);
240 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
241 EXPECT_STREQ(L"1.txt",
242 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
243 .c_str());
244
245 // Delete the first attachment.
246 EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
247 EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
248
249 // Verify the name of the new first attachment.
250 attachment = FPDFDoc_GetAttachment(document(), 0);
251 len = FPDFAttachment_GetName(attachment, nullptr, 0);
252 buf.clear();
253 buf.resize(len);
254 EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), len));
255 EXPECT_STREQ(L"attached.pdf",
256 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
257 .c_str());
258}