blob: 19147d4bae424911d7f711166a2494d5607acd72 [file] [log] [blame]
Tom Sepezc8f6ab62015-01-22 11:20:06 -08001// Copyright 2015 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
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05005#include <memory>
Dan Sinclair3ebd1212016-03-09 09:59:23 -05006#include <string>
7
dsinclaira52ab742016-09-29 13:59:29 -07008#include "core/fxcrt/fx_string.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -08009#include "public/fpdf_doc.h"
dsinclair1f5f2ff2016-04-25 14:14:56 -070010#include "public/fpdf_edit.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080011#include "public/fpdfview.h"
Wei Li091f7a02015-11-09 12:09:55 -080012#include "testing/embedder_test.h"
Tom Sepezc8f6ab62015-01-22 11:20:06 -080013#include "testing/gtest/include/gtest/gtest.h"
Dan Sinclair61046b92016-02-18 14:48:48 -050014#include "testing/test_support.h"
Tom Sepezc8f6ab62015-01-22 11:20:06 -080015
Nico Weber9d8ec5a2015-08-04 13:00:21 -070016class FPDFDocEmbeddertest : public EmbedderTest {};
Tom Sepezc8f6ab62015-01-22 11:20:06 -080017
18TEST_F(FPDFDocEmbeddertest, DestGetPageIndex) {
Wei Li091f7a02015-11-09 12:09:55 -080019 EXPECT_TRUE(OpenDocument("named_dests.pdf"));
Tom Sepezc8f6ab62015-01-22 11:20:06 -080020
21 // NULL FPDF_DEST case.
Lei Zhangb9c31972015-08-11 14:09:35 -070022 EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), nullptr));
Tom Sepezc8f6ab62015-01-22 11:20:06 -080023
24 // Page number directly in item from Dests NameTree.
25 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
thestig4997b222016-06-07 10:46:22 -070026 EXPECT_TRUE(dest);
Lei Zhangb9c31972015-08-11 14:09:35 -070027 EXPECT_EQ(1U, FPDFDest_GetPageIndex(document(), dest));
Tom Sepezc8f6ab62015-01-22 11:20:06 -080028
29 // Page number via object reference in item from Dests NameTree.
30 dest = FPDF_GetNamedDestByName(document(), "Next");
thestig4997b222016-06-07 10:46:22 -070031 EXPECT_TRUE(dest);
Lei Zhangb9c31972015-08-11 14:09:35 -070032 EXPECT_EQ(1U, FPDFDest_GetPageIndex(document(), dest));
Tom Sepezc8f6ab62015-01-22 11:20:06 -080033
34 // Page number directly in item from Dests dictionary.
35 dest = FPDF_GetNamedDestByName(document(), "FirstAlternate");
thestig4997b222016-06-07 10:46:22 -070036 EXPECT_TRUE(dest);
Lei Zhangb9c31972015-08-11 14:09:35 -070037 EXPECT_EQ(11U, FPDFDest_GetPageIndex(document(), dest));
Tom Sepezc8f6ab62015-01-22 11:20:06 -080038
39 // Invalid object reference in item from Dests NameTree.
40 dest = FPDF_GetNamedDestByName(document(), "LastAlternate");
thestig4997b222016-06-07 10:46:22 -070041 EXPECT_TRUE(dest);
Lei Zhangb9c31972015-08-11 14:09:35 -070042 EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), dest));
Tom Sepezc8f6ab62015-01-22 11:20:06 -080043}
Lei Zhange0947b32015-09-17 14:51:48 -070044
dsinclairc59fa882016-11-08 06:55:40 -080045TEST_F(FPDFDocEmbeddertest, DestGetLocationInPage) {
46 EXPECT_TRUE(OpenDocument("named_dests.pdf"));
47
48 // NULL FPDF_DEST case.
49 EXPECT_EQ(0U, FPDFDest_GetPageIndex(document(), nullptr));
50
51 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
52 EXPECT_TRUE(dest);
53
54 FPDF_BOOL hasX;
55 FPDF_BOOL hasY;
56 FPDF_BOOL hasZoom;
57 FS_FLOAT x;
58 FS_FLOAT y;
59 FS_FLOAT zoom;
60 EXPECT_TRUE(
61 FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &x, &y, &zoom));
62 EXPECT_TRUE(hasX);
63 EXPECT_TRUE(hasY);
64 EXPECT_TRUE(hasZoom);
65 EXPECT_EQ(0, x);
66 EXPECT_EQ(0, y);
67 EXPECT_EQ(1, zoom);
68}
69
tsepeze507dc52017-01-18 10:24:35 -080070TEST_F(FPDFDocEmbeddertest, BUG_680376) {
71 EXPECT_TRUE(OpenDocument("bug_680376.pdf"));
72
73 // Page number directly in item from Dests NameTree.
74 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), "First");
75 EXPECT_TRUE(dest);
76 EXPECT_EQ(static_cast<unsigned long>(-1),
77 FPDFDest_GetPageIndex(document(), dest));
78}
79
Lei Zhange0947b32015-09-17 14:51:48 -070080TEST_F(FPDFDocEmbeddertest, ActionGetFilePath) {
Wei Li091f7a02015-11-09 12:09:55 -080081 EXPECT_TRUE(OpenDocument("launch_action.pdf"));
Lei Zhange0947b32015-09-17 14:51:48 -070082
83 FPDF_PAGE page = FPDF_LoadPage(document(), 0);
84 ASSERT_TRUE(page);
85
86 // The target action is nearly the size of the whole page.
87 FPDF_LINK link = FPDFLink_GetLinkAtPoint(page, 100, 100);
88 ASSERT_TRUE(link);
89
90 FPDF_ACTION action = FPDFLink_GetAction(link);
91 ASSERT_TRUE(action);
92
93 const char kExpectedResult[] = "test.pdf";
94 const unsigned long kExpectedLength = sizeof(kExpectedResult);
95 unsigned long bufsize = FPDFAction_GetFilePath(action, nullptr, 0);
96 ASSERT_EQ(kExpectedLength, bufsize);
97
98 char buf[kExpectedLength];
99 EXPECT_EQ(bufsize, FPDFAction_GetFilePath(action, buf, bufsize));
100 EXPECT_EQ(std::string(kExpectedResult), std::string(buf));
101
102 FPDF_ClosePage(page);
103}
Tom Sepez758ae142015-10-14 09:26:32 -0700104
105TEST_F(FPDFDocEmbeddertest, NoBookmarks) {
106 // Open a file with no bookmarks.
Wei Li091f7a02015-11-09 12:09:55 -0800107 EXPECT_TRUE(OpenDocument("named_dests.pdf"));
Tom Sepez758ae142015-10-14 09:26:32 -0700108
109 // The non-existent top-level bookmark has no title.
110 unsigned short buf[128];
Wei Li05d53f02016-03-29 16:42:53 -0700111 EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf)));
Tom Sepez758ae142015-10-14 09:26:32 -0700112
113 // The non-existent top-level bookmark has no children.
114 EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), nullptr));
115}
116
117TEST_F(FPDFDocEmbeddertest, Bookmarks) {
118 // Open a file with two bookmarks.
Wei Li091f7a02015-11-09 12:09:55 -0800119 EXPECT_TRUE(OpenDocument("bookmarks.pdf"));
Tom Sepez758ae142015-10-14 09:26:32 -0700120
121 // The existent top-level bookmark has no title.
122 unsigned short buf[128];
Wei Li05d53f02016-03-29 16:42:53 -0700123 EXPECT_EQ(0u, FPDFBookmark_GetTitle(nullptr, buf, sizeof(buf)));
Tom Sepez758ae142015-10-14 09:26:32 -0700124
125 FPDF_BOOKMARK child = FPDFBookmark_GetFirstChild(document(), nullptr);
thestig4997b222016-06-07 10:46:22 -0700126 EXPECT_TRUE(child);
Wei Li05d53f02016-03-29 16:42:53 -0700127 EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400128 EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));
Tom Sepez758ae142015-10-14 09:26:32 -0700129
130 EXPECT_EQ(nullptr, FPDFBookmark_GetFirstChild(document(), child));
131
132 FPDF_BOOKMARK sibling = FPDFBookmark_GetNextSibling(document(), child);
thestig4997b222016-06-07 10:46:22 -0700133 EXPECT_TRUE(sibling);
Wei Li05d53f02016-03-29 16:42:53 -0700134 EXPECT_EQ(28u, FPDFBookmark_GetTitle(sibling, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400135 EXPECT_EQ(WideString(L"A Good Ending"), WideString::FromUTF16LE(buf, 13));
Tom Sepez758ae142015-10-14 09:26:32 -0700136
137 EXPECT_EQ(nullptr, FPDFBookmark_GetNextSibling(document(), sibling));
138}
Tom Sepez0861c162016-01-04 16:35:52 -0800139
140TEST_F(FPDFDocEmbeddertest, FindBookmarks) {
Tom Sepez8ab45ea2016-01-05 10:17:30 -0800141 // Open a file with two bookmarks.
Tom Sepez0861c162016-01-04 16:35:52 -0800142 EXPECT_TRUE(OpenDocument("bookmarks.pdf"));
143
Tom Sepez8ab45ea2016-01-05 10:17:30 -0800144 // Find the first one, based on its known title.
Tom Sepez0aa35312016-01-06 10:16:32 -0800145 std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
146 GetFPDFWideString(L"A Good Beginning");
147 FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get());
thestig4997b222016-06-07 10:46:22 -0700148 EXPECT_TRUE(child);
Tom Sepez8ab45ea2016-01-05 10:17:30 -0800149
150 // Check that the string matches.
151 unsigned short buf[128];
Wei Li05d53f02016-03-29 16:42:53 -0700152 EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400153 EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));
Tom Sepez0861c162016-01-04 16:35:52 -0800154
Tom Sepez8ab45ea2016-01-05 10:17:30 -0800155 // Check that it is them same as the one returned by GetFirstChild.
156 EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr));
Tom Sepez0861c162016-01-04 16:35:52 -0800157
158 // Try to find one using a non-existent title.
Tom Sepez0aa35312016-01-06 10:16:32 -0800159 std::unique_ptr<unsigned short, pdfium::FreeDeleter> bad_title =
160 GetFPDFWideString(L"A BAD Beginning");
161 EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get()));
Tom Sepez0861c162016-01-04 16:35:52 -0800162}
Wei Li0e2e5d72016-03-03 11:28:06 -0800163
164// Check circular bookmarks will not cause infinite loop.
165TEST_F(FPDFDocEmbeddertest, FindBookmarks_bug420) {
166 // Open a file with circular bookmarks.
167 EXPECT_TRUE(OpenDocument("bookmarks_circular.pdf"));
168
169 // Try to find a title.
170 std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
171 GetFPDFWideString(L"anything");
172 EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), title.get()));
173}
dsinclair1f5f2ff2016-04-25 14:14:56 -0700174
175TEST_F(FPDFDocEmbeddertest, DeletePage) {
176 EXPECT_TRUE(OpenDocument("hello_world.pdf"));
177 EXPECT_EQ(1, FPDF_GetPageCount(document()));
178 FPDFPage_Delete(document(), 0);
179 EXPECT_EQ(0, FPDF_GetPageCount(document()));
180}
thestig733e0682016-11-23 05:52:39 -0800181
Lei Zhang188cf0c2017-09-14 12:58:41 -0700182TEST_F(FPDFDocEmbeddertest, GetMetaText) {
183 ASSERT_TRUE(OpenDocument("bug_601362.pdf"));
184
185 // Invalid document / tag results in 0.
186 unsigned short buf[128];
187 EXPECT_EQ(0u, FPDF_GetMetaText(document(), nullptr, buf, sizeof(buf)));
188 EXPECT_EQ(0u, FPDF_GetMetaText(nullptr, "", buf, sizeof(buf)));
189
190 // Tags that do not eixst results in an empty wide string.
191 EXPECT_EQ(2u, FPDF_GetMetaText(document(), "", buf, sizeof(buf)));
192 EXPECT_EQ(2u, FPDF_GetMetaText(document(), "foo", buf, sizeof(buf)));
193 ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Title", buf, sizeof(buf)));
194 ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Author", buf, sizeof(buf)));
195 ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Subject", buf, sizeof(buf)));
196 ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Keywords", buf, sizeof(buf)));
197 ASSERT_EQ(2u, FPDF_GetMetaText(document(), "Producer", buf, sizeof(buf)));
198
199 constexpr wchar_t kExpectedCreator[] = L"Microsoft Word";
200 ASSERT_EQ(30u, FPDF_GetMetaText(document(), "Creator", buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400201 EXPECT_EQ(WideString(kExpectedCreator),
202 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreator)));
Lei Zhang188cf0c2017-09-14 12:58:41 -0700203
204 constexpr wchar_t kExpectedCreationDate[] = L"D:20160411190039+00'00'";
205 ASSERT_EQ(48u,
206 FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400207 EXPECT_EQ(WideString(kExpectedCreationDate),
208 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedCreationDate)));
Lei Zhang188cf0c2017-09-14 12:58:41 -0700209
210 constexpr wchar_t kExpectedModDate[] = L"D:20160411190039+00'00'";
211 ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400212 EXPECT_EQ(WideString(kExpectedModDate),
213 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
Lei Zhang188cf0c2017-09-14 12:58:41 -0700214}
215
Lei Zhang753818a2017-09-14 13:41:52 -0700216TEST_F(FPDFDocEmbeddertest, GetMetaTextSameObjectNumber) {
217 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
218
219 // The PDF has been edited. It has two %%EOF markers, and 2 objects numbered
220 // (1 0). Both objects are /Info dictionaries, but contain different data.
221 // Make sure ModDate is the date of the last modification.
222 unsigned short buf[128];
223 constexpr wchar_t kExpectedModDate[] = L"D:20170612232940-04'00'";
224 ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400225 EXPECT_EQ(WideString(kExpectedModDate),
226 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
Lei Zhang753818a2017-09-14 13:41:52 -0700227}
228
229TEST_F(FPDFDocEmbeddertest, GetMetaTextInAttachmentFile) {
230 ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
231
232 // Make sure this is the date from the PDF itself and not the attached PDF.
233 unsigned short buf[128];
234 constexpr wchar_t kExpectedModDate[] = L"D:20170712214448-07'00'";
235 ASSERT_EQ(48u, FPDF_GetMetaText(document(), "ModDate", buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400236 EXPECT_EQ(WideString(kExpectedModDate),
237 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedModDate)));
Lei Zhang753818a2017-09-14 13:41:52 -0700238}
239
thestig733e0682016-11-23 05:52:39 -0800240TEST_F(FPDFDocEmbeddertest, NoPageLabels) {
241 EXPECT_TRUE(OpenDocument("about_blank.pdf"));
242 EXPECT_EQ(1, FPDF_GetPageCount(document()));
243
dsinclair6bdb56c2016-12-06 09:53:27 -0800244 ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 0, nullptr, 0));
thestig733e0682016-11-23 05:52:39 -0800245}
246
247TEST_F(FPDFDocEmbeddertest, GetPageLabels) {
248 EXPECT_TRUE(OpenDocument("page_labels.pdf"));
249 EXPECT_EQ(7, FPDF_GetPageCount(document()));
250
Artem Strygin0e60b9e2017-09-28 18:46:03 +0300251 // We do not request labels, when use FPDFAvail_IsXXXAvail.
252 // Flush all data, to allow read labels.
253 SetWholeFileAvailable();
254
thestig733e0682016-11-23 05:52:39 -0800255 unsigned short buf[128];
dsinclair6bdb56c2016-12-06 09:53:27 -0800256 EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -2, buf, sizeof(buf)));
257 EXPECT_EQ(0u, FPDF_GetPageLabel(document(), -1, buf, sizeof(buf)));
thestig733e0682016-11-23 05:52:39 -0800258
Dan Sinclair812e96c2017-03-13 16:43:37 -0400259 const wchar_t kExpectedPageLabel0[] = L"i";
dsinclair6bdb56c2016-12-06 09:53:27 -0800260 ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 0, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400261 EXPECT_EQ(WideString(kExpectedPageLabel0),
262 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel0)));
thestig733e0682016-11-23 05:52:39 -0800263
Dan Sinclair812e96c2017-03-13 16:43:37 -0400264 const wchar_t kExpectedPageLabel1[] = L"ii";
dsinclair6bdb56c2016-12-06 09:53:27 -0800265 ASSERT_EQ(6u, FPDF_GetPageLabel(document(), 1, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400266 EXPECT_EQ(WideString(kExpectedPageLabel1),
267 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel1)));
thestig733e0682016-11-23 05:52:39 -0800268
Dan Sinclair812e96c2017-03-13 16:43:37 -0400269 const wchar_t kExpectedPageLabel2[] = L"1";
dsinclair6bdb56c2016-12-06 09:53:27 -0800270 ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 2, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400271 EXPECT_EQ(WideString(kExpectedPageLabel2),
272 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel2)));
thestig733e0682016-11-23 05:52:39 -0800273
Dan Sinclair812e96c2017-03-13 16:43:37 -0400274 const wchar_t kExpectedPageLabel3[] = L"2";
dsinclair6bdb56c2016-12-06 09:53:27 -0800275 ASSERT_EQ(4u, FPDF_GetPageLabel(document(), 3, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400276 EXPECT_EQ(WideString(kExpectedPageLabel3),
277 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel3)));
thestig733e0682016-11-23 05:52:39 -0800278
Dan Sinclair812e96c2017-03-13 16:43:37 -0400279 const wchar_t kExpectedPageLabel4[] = L"zzA";
dsinclair6bdb56c2016-12-06 09:53:27 -0800280 ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 4, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400281 EXPECT_EQ(WideString(kExpectedPageLabel4),
282 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel4)));
thestig733e0682016-11-23 05:52:39 -0800283
Dan Sinclair812e96c2017-03-13 16:43:37 -0400284 const wchar_t kExpectedPageLabel5[] = L"zzB";
dsinclair6bdb56c2016-12-06 09:53:27 -0800285 ASSERT_EQ(8u, FPDF_GetPageLabel(document(), 5, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400286 EXPECT_EQ(WideString(kExpectedPageLabel5),
287 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel5)));
thestig733e0682016-11-23 05:52:39 -0800288
Dan Sinclair812e96c2017-03-13 16:43:37 -0400289 const wchar_t kExpectedPageLabel6[] = L"";
dsinclair6bdb56c2016-12-06 09:53:27 -0800290 ASSERT_EQ(2u, FPDF_GetPageLabel(document(), 6, buf, sizeof(buf)));
Ryan Harrison275e2602017-09-18 14:23:18 -0400291 EXPECT_EQ(WideString(kExpectedPageLabel6),
292 WideString::FromUTF16LE(buf, FXSYS_len(kExpectedPageLabel6)));
thestig733e0682016-11-23 05:52:39 -0800293
dsinclair6bdb56c2016-12-06 09:53:27 -0800294 ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 7, buf, sizeof(buf)));
295 ASSERT_EQ(0u, FPDF_GetPageLabel(document(), 8, buf, sizeof(buf)));
thestig733e0682016-11-23 05:52:39 -0800296}