blob: 6ab82f836647e119a63d5d7a9c74300f4d8aee00 [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 Zhang4c64e962019-02-05 19:24:12 +000012#include "testing/utils/hash.h"
Jane Liu53aafa92017-07-12 19:55:02 -040013
Lei Zhangdf064df2017-08-31 02:33:27 -070014static constexpr char kDateKey[] = "CreationDate";
15static constexpr char kChecksumKey[] = "CheckSum";
16
Lei Zhangab41f252018-12-23 03:10:50 +000017class FPDFAttachmentEmbedderTest : public EmbedderTest {};
Jane Liu53aafa92017-07-12 19:55:02 -040018
Lei Zhangab41f252018-12-23 03:10:50 +000019TEST_F(FPDFAttachmentEmbedderTest, ExtractAttachments) {
Jane Liu53aafa92017-07-12 19:55:02 -040020 // Open a file with two attachments.
21 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
22 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
23
Jane Liu18ae06d2017-07-18 10:15:16 -040024 // Retrieve the first attachment.
25 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
26 ASSERT_TRUE(attachment);
27
Jane Liu53aafa92017-07-12 19:55:02 -040028 // Check that the name of the first attachment is correct.
Jane Liu18ae06d2017-07-18 10:15:16 -040029 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
Jane Liu53aafa92017-07-12 19:55:02 -040030 std::vector<char> buf(len);
Jane Liu18ae06d2017-07-18 10:15:16 -040031 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
Jane Liu53aafa92017-07-12 19:55:02 -040032 EXPECT_STREQ(L"1.txt",
33 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
34 .c_str());
Jane Liu18ae06d2017-07-18 10:15:16 -040035
36 // Check that the content of the first attachment is correct.
37 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
38 buf.clear();
39 buf.resize(len);
40 ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len));
41 EXPECT_EQ(std::string("test"), std::string(buf.data(), 4));
42
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 Zhangdf064df2017-08-31 02:33:27 -070054 len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
Jane Liu18ae06d2017-07-18 10:15:16 -040055 buf.clear();
56 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -070057 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
58 len));
Jane Liu18ae06d2017-07-18 10:15:16 -040059 EXPECT_STREQ(L"D:20170712214438-07'00'",
60 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
61 .c_str());
62
63 // Retrieve the second attachment.
64 attachment = FPDFDoc_GetAttachment(document(), 1);
65 ASSERT_TRUE(attachment);
66
67 // Retrieve the second attachment file.
68 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
69 buf.clear();
70 buf.resize(len);
71 EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len));
72
73 // Check that the calculated checksum of the file data matches expectation.
74 const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
75 const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
76 const std::string generated_checksum =
77 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len);
78 EXPECT_EQ(kCheckSum, generated_checksum);
79
80 // Check that the stored checksum matches expectation.
Lei Zhangdf064df2017-08-31 02:33:27 -070081 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu18ae06d2017-07-18 10:15:16 -040082 buf.clear();
83 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -070084 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu18ae06d2017-07-18 10:15:16 -040085 buf.data(), len));
86 EXPECT_EQ(kCheckSumW,
87 GetPlatformWString(reinterpret_cast<unsigned short*>(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.
99 std::unique_ptr<unsigned short, pdfium::FreeDeleter> file_name =
100 GetFPDFWideString(L"0.txt");
101 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.
162 std::unique_ptr<unsigned short, pdfium::FreeDeleter> file_name =
163 GetFPDFWideString(L"5.txt");
164 FPDF_ATTACHMENT attachment =
165 FPDFDoc_AddAttachment(document(), file_name.get());
166 constexpr char kContents[] = "Hello World!";
167 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents,
168 strlen(kContents)));
169
170 // Set the date to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400171 constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
172 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_date =
173 GetFPDFWideString(kDateW);
174 EXPECT_TRUE(
Lei Zhangdf064df2017-08-31 02:33:27 -0700175 FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get()));
Jane Liu54a42142017-07-24 16:40:54 -0400176
177 // Set the checksum to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400178 constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
179 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_checksum =
180 GetFPDFWideString(kCheckSumW);
Lei Zhangdf064df2017-08-31 02:33:27 -0700181 EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400182 ws_checksum.get()));
183
184 // Verify the name of the new attachment (i.e. the second attachment).
185 attachment = FPDFDoc_GetAttachment(document(), 1);
186 ASSERT_TRUE(attachment);
187 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
188 std::vector<char> buf(len);
189 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
190 EXPECT_STREQ(L"5.txt",
191 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
192 .c_str());
193
194 // Verify the content of the new attachment.
195 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
196 buf.clear();
197 buf.resize(len);
198 ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len));
199 EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12));
200
201 // Verify the creation date of the new attachment.
Lei Zhangdf064df2017-08-31 02:33:27 -0700202 len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400203 buf.clear();
204 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700205 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
206 len));
Jane Liu54a42142017-07-24 16:40:54 -0400207 EXPECT_STREQ(kDateW,
208 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
209 .c_str());
210
211 // Verify the checksum of the new attachment.
Lei Zhangdf064df2017-08-31 02:33:27 -0700212 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400213 buf.clear();
214 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700215 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400216 buf.data(), len));
217 EXPECT_STREQ(kCheckSumW,
218 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
219 .c_str());
220
221 // Overwrite the existing file with empty content, and check that the checksum
222 // gets updated to the correct value.
223 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
224 EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
Lei Zhangdf064df2017-08-31 02:33:27 -0700225 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400226 buf.clear();
227 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700228 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400229 buf.data(), len));
230 EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
231 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
Jane Liuf63e8132017-07-25 18:11:27 -0400232}
233
Lei Zhangab41f252018-12-23 03:10:50 +0000234TEST_F(FPDFAttachmentEmbedderTest, DeleteAttachment) {
Jane Liuf63e8132017-07-25 18:11:27 -0400235 // Open a file with two attachments.
236 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
237 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
238
239 // Verify the name of the first attachment.
240 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
241 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
242 std::vector<char> buf(len);
243 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
244 EXPECT_STREQ(L"1.txt",
245 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
246 .c_str());
247
248 // Delete the first attachment.
249 EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
250 EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
251
252 // Verify the name of the new first attachment.
253 attachment = FPDFDoc_GetAttachment(document(), 0);
254 len = FPDFAttachment_GetName(attachment, nullptr, 0);
255 buf.clear();
256 buf.resize(len);
257 EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), len));
258 EXPECT_STREQ(L"attached.pdf",
259 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
260 .c_str());
261}