blob: dd9b5aebf38a3b25d0605ac60495da6b04f24138 [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"
12
Lei Zhangdf064df2017-08-31 02:33:27 -070013static constexpr char kDateKey[] = "CreationDate";
14static constexpr char kChecksumKey[] = "CheckSum";
15
Jane Liu53aafa92017-07-12 19:55:02 -040016class FPDFAttachmentEmbeddertest : public EmbedderTest {};
17
18TEST_F(FPDFAttachmentEmbeddertest, ExtractAttachments) {
19 // Open a file with two attachments.
20 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
21 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
22
Jane Liu18ae06d2017-07-18 10:15:16 -040023 // Retrieve the first attachment.
24 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
25 ASSERT_TRUE(attachment);
26
Jane Liu53aafa92017-07-12 19:55:02 -040027 // Check that the name of the first attachment is correct.
Jane Liu18ae06d2017-07-18 10:15:16 -040028 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
Jane Liu53aafa92017-07-12 19:55:02 -040029 std::vector<char> buf(len);
Jane Liu18ae06d2017-07-18 10:15:16 -040030 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
Jane Liu53aafa92017-07-12 19:55:02 -040031 EXPECT_STREQ(L"1.txt",
32 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
33 .c_str());
Jane Liu18ae06d2017-07-18 10:15:16 -040034
35 // Check that the content of the first attachment is correct.
36 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
37 buf.clear();
38 buf.resize(len);
39 ASSERT_EQ(4u, FPDFAttachment_GetFile(attachment, buf.data(), len));
40 EXPECT_EQ(std::string("test"), std::string(buf.data(), 4));
41
42 // Check that a non-existent key does not exist.
Lei Zhangdf064df2017-08-31 02:33:27 -070043 EXPECT_FALSE(FPDFAttachment_HasKey(attachment, "none"));
Jane Liu18ae06d2017-07-18 10:15:16 -040044
45 // Check that the string value of a non-string dictionary entry is empty.
Lei Zhangdf064df2017-08-31 02:33:27 -070046 static constexpr char kSizeKey[] = "Size";
Jane Liu18ae06d2017-07-18 10:15:16 -040047 EXPECT_EQ(FPDF_OBJECT_NUMBER,
Lei Zhangdf064df2017-08-31 02:33:27 -070048 FPDFAttachment_GetValueType(attachment, kSizeKey));
49 EXPECT_EQ(2u,
50 FPDFAttachment_GetStringValue(attachment, kSizeKey, nullptr, 0));
Jane Liu18ae06d2017-07-18 10:15:16 -040051
52 // Check that the creation date of the first attachment is correct.
Lei Zhangdf064df2017-08-31 02:33:27 -070053 len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
Jane Liu18ae06d2017-07-18 10:15:16 -040054 buf.clear();
55 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -070056 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
57 len));
Jane Liu18ae06d2017-07-18 10:15:16 -040058 EXPECT_STREQ(L"D:20170712214438-07'00'",
59 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
60 .c_str());
61
62 // Retrieve the second attachment.
63 attachment = FPDFDoc_GetAttachment(document(), 1);
64 ASSERT_TRUE(attachment);
65
66 // Retrieve the second attachment file.
67 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
68 buf.clear();
69 buf.resize(len);
70 EXPECT_EQ(5869u, FPDFAttachment_GetFile(attachment, buf.data(), len));
71
72 // Check that the calculated checksum of the file data matches expectation.
73 const char kCheckSum[] = "72afcddedf554dda63c0c88e06f1ce18";
74 const wchar_t kCheckSumW[] = L"<72AFCDDEDF554DDA63C0C88E06F1CE18>";
75 const std::string generated_checksum =
76 GenerateMD5Base16(reinterpret_cast<uint8_t*>(buf.data()), len);
77 EXPECT_EQ(kCheckSum, generated_checksum);
78
79 // Check that the stored checksum matches expectation.
Lei Zhangdf064df2017-08-31 02:33:27 -070080 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu18ae06d2017-07-18 10:15:16 -040081 buf.clear();
82 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -070083 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu18ae06d2017-07-18 10:15:16 -040084 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.
Jane Liu54a42142017-07-24 16:40:54 -0400170 constexpr wchar_t kDateW[] = L"D:20170720161527-04'00'";
171 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_date =
172 GetFPDFWideString(kDateW);
173 EXPECT_TRUE(
Lei Zhangdf064df2017-08-31 02:33:27 -0700174 FPDFAttachment_SetStringValue(attachment, kDateKey, ws_date.get()));
Jane Liu54a42142017-07-24 16:40:54 -0400175
176 // Set the checksum to be an arbitrary value.
Jane Liu54a42142017-07-24 16:40:54 -0400177 constexpr wchar_t kCheckSumW[] = L"<ABCDEF01234567899876543210FEDCBA>";
178 std::unique_ptr<unsigned short, pdfium::FreeDeleter> ws_checksum =
179 GetFPDFWideString(kCheckSumW);
Lei Zhangdf064df2017-08-31 02:33:27 -0700180 EXPECT_TRUE(FPDFAttachment_SetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400181 ws_checksum.get()));
182
183 // Verify the name of the new attachment (i.e. the second attachment).
184 attachment = FPDFDoc_GetAttachment(document(), 1);
185 ASSERT_TRUE(attachment);
186 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
187 std::vector<char> buf(len);
188 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
189 EXPECT_STREQ(L"5.txt",
190 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
191 .c_str());
192
193 // Verify the content of the new attachment.
194 len = FPDFAttachment_GetFile(attachment, nullptr, 0);
195 buf.clear();
196 buf.resize(len);
197 ASSERT_EQ(12u, FPDFAttachment_GetFile(attachment, buf.data(), len));
198 EXPECT_EQ(std::string(kContents), std::string(buf.data(), 12));
199
200 // Verify the creation date of the new attachment.
Lei Zhangdf064df2017-08-31 02:33:27 -0700201 len = FPDFAttachment_GetStringValue(attachment, kDateKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400202 buf.clear();
203 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700204 EXPECT_EQ(48u, FPDFAttachment_GetStringValue(attachment, kDateKey, buf.data(),
205 len));
Jane Liu54a42142017-07-24 16:40:54 -0400206 EXPECT_STREQ(kDateW,
207 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
208 .c_str());
209
210 // Verify the checksum of the new attachment.
Lei Zhangdf064df2017-08-31 02:33:27 -0700211 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400212 buf.clear();
213 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700214 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400215 buf.data(), len));
216 EXPECT_STREQ(kCheckSumW,
217 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
218 .c_str());
219
220 // Overwrite the existing file with empty content, and check that the checksum
221 // gets updated to the correct value.
222 EXPECT_TRUE(FPDFAttachment_SetFile(attachment, document(), nullptr, 0));
223 EXPECT_EQ(0u, FPDFAttachment_GetFile(attachment, nullptr, 0));
Lei Zhangdf064df2017-08-31 02:33:27 -0700224 len = FPDFAttachment_GetStringValue(attachment, kChecksumKey, nullptr, 0);
Jane Liu54a42142017-07-24 16:40:54 -0400225 buf.clear();
226 buf.resize(len);
Lei Zhangdf064df2017-08-31 02:33:27 -0700227 EXPECT_EQ(70u, FPDFAttachment_GetStringValue(attachment, kChecksumKey,
Jane Liu54a42142017-07-24 16:40:54 -0400228 buf.data(), len));
229 EXPECT_EQ(L"<D41D8CD98F00B204E9800998ECF8427E>",
230 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data())));
Jane Liuf63e8132017-07-25 18:11:27 -0400231}
232
233TEST_F(FPDFAttachmentEmbeddertest, DeleteAttachment) {
234 // Open a file with two attachments.
235 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
236 EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
237
238 // Verify the name of the first attachment.
239 FPDF_ATTACHMENT attachment = FPDFDoc_GetAttachment(document(), 0);
240 unsigned long len = FPDFAttachment_GetName(attachment, nullptr, 0);
241 std::vector<char> buf(len);
242 EXPECT_EQ(12u, FPDFAttachment_GetName(attachment, buf.data(), len));
243 EXPECT_STREQ(L"1.txt",
244 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
245 .c_str());
246
247 // Delete the first attachment.
248 EXPECT_TRUE(FPDFDoc_DeleteAttachment(document(), 0));
249 EXPECT_EQ(1, FPDFDoc_GetAttachmentCount(document()));
250
251 // Verify the name of the new first attachment.
252 attachment = FPDFDoc_GetAttachment(document(), 0);
253 len = FPDFAttachment_GetName(attachment, nullptr, 0);
254 buf.clear();
255 buf.resize(len);
256 EXPECT_EQ(26u, FPDFAttachment_GetName(attachment, buf.data(), len));
257 EXPECT_STREQ(L"attached.pdf",
258 GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
259 .c_str());
260}