blob: f4d0bfcfae842d9581df5e777118c76ac302c6ea [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
5#include "public/fpdf_attachment.h"
Jane Liu18ae06d2017-07-18 10:15:16 -04006#include "public/fpdfview.h"
Jane Liu53aafa92017-07-12 19:55:02 -04007#include "testing/embedder_test.h"
8
9class FPDFAttachmentEmbeddertest : public EmbedderTest {};
10
11TEST_F(FPDFAttachmentEmbeddertest, ExtractAttachments) {
12 // Open a file with two attachments.
13 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
14 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
15
Jane Liu18ae06d2017-07-18 10:15:16 -040016 // Retrieve the first attachment.
17 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
18 ASSERT_TRUE(attachment);
19
Jane Liu53aafa92017-07-12 19:55:02 -040020 // Check that the name of the first attachment is correct.
Jane Liu18ae06d2017-07-18 10:15:16 -040021 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
Jane Liu53aafa92017-07-12 19:55:02 -040022 std::vector<char> buf(len);
Jane Liu18ae06d2017-07-18 10:15:16 -040023 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
Jane Liu53aafa92017-07-12 19:55:02 -040024 EXPECT_STREQ(L"1.txt",
25 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
26 .c_str());
Jane Liu18ae06d2017-07-18 10:15:16 -040027
28 // Check that the content of the first attachment is correct.
29 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
30 buf.clear();
31 buf.resize(len);
32 ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len));
33 EXPECT_EQ(std::string("test"), std::string(buf.data(), 4));
34
35 // Check that a non-existent key does not exist.
36 EXPECT_FALSE(
37 FPDFAttachment_HasKey(attachment, GetFPDFWideString(L"none").get()));
38
39 // Check that the string value of a non-string dictionary entry is empty.
40 std::unique_ptr<unsigned short, pdfium::FreeDeleter> size_key =
41 GetFPDFWideString(L"Size");
42 EXPECT_EQ(FPDF_OBJECT_NUMBER,
43 FPDFAttachment_GetValueType(attachment, size_key.get()));
44 EXPECT_EQ(2u, FPDFAttachment_GetStringValue(attachment, size_key.get(),
45 nullptr, 0));
46
47 // Check that the creation date of the first attachment is correct.
48 std::unique_ptr<unsigned short, pdfium::FreeDeleter> date_key =
49 GetFPDFWideString(L"CreationDate");
50 len = FPDFAttachment_GetStringValue(attachment, date_key.get(), nullptr, 0);
51 buf.clear();
52 buf.resize(len);
53 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, date_key.get(),
54 buf.data(), len));
55 EXPECT_STREQ(L"D:20170712214438-07'00'",
56 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
57 .c_str());
58
59 // Retrieve the second attachment.
60 attachment = FPDFDoc_GetAttachment(document(), 1);
61 ASSERT_TRUE(attachment);
62
63 // Retrieve the second attachment file.
64 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
65 buf.clear();
66 buf.resize(len);
67 EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len));
68
69 // Check that the calculated checksum of the file data matches expectation.
70 const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
71 const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
72 const std::string generated_checksum =
73 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len);
74 EXPECT_EQ(kCheckSum, generated_checksum);
75
76 // Check that the stored checksum matches expectation.
77 std::unique_ptr<unsigned short, pdfium::FreeDeleter> checksum_key =
78 GetFPDFWideString(L"CheckSum");
79 len =
80 FPDFAttachment_GetStringValue(attachment, checksum_key.get(), nullptr, 0);
81 buf.clear();
82 buf.resize(len);
83 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, checksum_key.get(),
84 buf.data(), len));
85 EXPECT_EQ(kCheckSumW,
86 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
Jane Liu53aafa92017-07-12 19:55:02 -040087}
Jane Liu54a42142017-07-24 16:40:54 -040088
89TEST_F(FPDFAttachmentEmbeddertest, AddAttachments) {
90 // Open a file with two attachments.
91 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
92 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
93
94 // Check that adding an attachment with an empty name would fail.
95 EXPECT_FALSE(FPDFDoc_AddAttachment(document(), nullptr));
96
97 // Add an attachment to the beginning of the embedded file list.
98 std::unique_ptr<unsigned short, pdfium::FreeDeleter> file_name =
99 GetFPDFWideString(L"0.txt");
100 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);
114 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
115 std::vector<char> buf(len);
116 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
117 EXPECT_STREQ(L"0.txt",
118 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
119 .c_str());
120
121 // Verify the content of the new attachment (i.e. the first attachment).
122 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
123 buf.clear();
124 buf.resize(len);
125 ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
126 EXPECT_EQ(std::string(kContents1), std::string(buf.data(), 6));
127
128 // Add an attachment to the end of the embedded file list and set its file.
129 file_name = GetFPDFWideString(L"z.txt");
130 attachment = FPDFDoc_AddAttachment(document(), file_name.get());
131 constexpr char kContents2[] = "World!";
132 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), kContents2,
133 strlen(kContents2)));
134 EXPECT_EQ(4, FPDFDoc_GetAttachmentCount(document()));
135
136 // Verify the name of the new attachment (i.e. the fourth attachment).
137 attachment = FPDFDoc_GetAttachment(document(), 3);
138 ASSERT_TRUE(attachment);
139 len = FPDFAttachment_GetName(attachment, nullptr, 0);
140 buf.clear();
141 buf.resize(len);
142 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
143 EXPECT_STREQ(L"z.txt",
144 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
145 .c_str());
146
147 // Verify the content of the new attachment (i.e. the fourth attachment).
148 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
149 buf.clear();
150 buf.resize(len);
151 ASSERT_EQ(6u, FPDFAttachment_GetFile(attachment, buf.data(), len));
152 EXPECT_EQ(std::string(kContents2), std::string(buf.data(), 6));
153}
154
155TEST_F(FPDFAttachmentEmbeddertest, AddAttachmentsWithParams) {
156 // Open a file with two attachments.
157 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
158 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
159
160 // Add an attachment to the embedded file list.
161 std::unique_ptr<unsigned short, pdfium::FreeDeleter> file_name =
162 GetFPDFWideString(L"5.txt");
163 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.
170 std::unique_ptr<unsigned short, pdfium::FreeDeleter> date_key =
171 GetFPDFWideString(L"CreationDate");
172 constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
173 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_date =
174 GetFPDFWideString(kDateW);
175 EXPECT_TRUE(
176 FPDFAttachment_SetStringValue(attachment, date_key.get(), ws_date.get()));
177
178 // Set the checksum to be an arbitrary value.
179 std::unique_ptr<unsigned short, pdfium::FreeDeleter> checksum_key =
180 GetFPDFWideString(L"CheckSum");
181 constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
182 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_checksum =
183 GetFPDFWideString(kCheckSumW);
184 EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, checksum_key.get(),
185 ws_checksum.get()));
186
187 // Verify the name of the new attachment (i.e. the second attachment).
188 attachment = FPDFDoc_GetAttachment(document(), 1);
189 ASSERT_TRUE(attachment);
190 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
191 std::vector<char> buf(len);
192 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
193 EXPECT_STREQ(L"5.txt",
194 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
195 .c_str());
196
197 // Verify the content of the new attachment.
198 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
199 buf.clear();
200 buf.resize(len);
201 ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len));
202 EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12));
203
204 // Verify the creation date of the new attachment.
205 len = FPDFAttachment_GetStringValue(attachment, date_key.get(), nullptr, 0);
206 buf.clear();
207 buf.resize(len);
208 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, date_key.get(),
209 buf.data(), len));
210 EXPECT_STREQ(kDateW,
211 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
212 .c_str());
213
214 // Verify the checksum of the new attachment.
215 len =
216 FPDFAttachment_GetStringValue(attachment, checksum_key.get(), nullptr, 0);
217 buf.clear();
218 buf.resize(len);
219 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, checksum_key.get(),
220 buf.data(), len));
221 EXPECT_STREQ(kCheckSumW,
222 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
223 .c_str());
224
225 // Overwrite the existing file with empty content, and check that the checksum
226 // gets updated to the correct value.
227 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
228 EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
229 len =
230 FPDFAttachment_GetStringValue(attachment, checksum_key.get(), nullptr, 0);
231 buf.clear();
232 buf.resize(len);
233 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, checksum_key.get(),
234 buf.data(), len));
235 EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
236 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
237}