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