blob: 459f8d5ced281dbdb745413aa9a16d2f2ed9c889 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdf_doc.h"
8
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009#include <memory>
Wei Li0e2e5d72016-03-03 11:28:06 -080010#include <set>
Tom Sepezd524d322019-05-28 21:52:27 +000011#include <utility>
Wei Li0e2e5d72016-03-03 11:28:06 -080012
Zhouhan Chen16760b52020-08-12 05:14:00 +000013#include "constants/form_fields.h"
Virender Singhceea6072020-06-18 20:31:25 +000014#include "core/fpdfapi/page/cpdf_annotcontext.h"
dsinclair41872fa2016-10-04 11:29:35 -070015#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070016#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000017#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070018#include "core/fpdfapi/parser/cpdf_document.h"
Ralf Sippl16381792018-04-12 21:20:26 +000019#include "core/fpdfapi/parser/cpdf_number.h"
Daniel Hosseinianf2e36012020-04-14 02:40:57 +000020#include "core/fpdfapi/parser/cpdf_string.h"
21#include "core/fpdfapi/parser/fpdf_parser_decode.h"
Zhouhan Chen16760b52020-08-12 05:14:00 +000022#include "core/fpdfdoc/cpdf_aaction.h"
dsinclair1727aee2016-09-29 13:12:56 -070023#include "core/fpdfdoc/cpdf_bookmark.h"
24#include "core/fpdfdoc/cpdf_bookmarktree.h"
dsinclairc59fa882016-11-08 06:55:40 -080025#include "core/fpdfdoc/cpdf_dest.h"
Tom Sepezd524d322019-05-28 21:52:27 +000026#include "core/fpdfdoc/cpdf_linklist.h"
thestig733e0682016-11-23 05:52:39 -080027#include "core/fpdfdoc/cpdf_pagelabel.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000028#include "fpdfsdk/cpdfsdk_helpers.h"
Zhouhan Chen16760b52020-08-12 05:14:00 +000029#include "public/fpdf_formfill.h"
Tom Sepez9c78c0d2021-01-27 20:13:14 +000030#include "third_party/base/check.h"
Lei Zhang87e3d7a2021-06-17 19:40:28 +000031#include "third_party/base/containers/contains.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070032
Lei Zhangbdf72c32015-08-14 19:24:08 -070033namespace {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070034
Lei Zhangbdf72c32015-08-14 19:24:08 -070035CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree,
36 CPDF_Bookmark bookmark,
Ryan Harrison275e2602017-09-18 14:23:18 -040037 const WideString& title,
Lei Zhang5cee3f22018-05-25 21:48:49 +000038 std::set<const CPDF_Dictionary*>* visited) {
Wei Li0e2e5d72016-03-03 11:28:06 -080039 // Return if already checked to avoid circular calling.
Lei Zhangf245ae62020-05-15 21:49:46 +000040 if (pdfium::Contains(*visited, bookmark.GetDict()))
Wei Li0e2e5d72016-03-03 11:28:06 -080041 return CPDF_Bookmark();
42 visited->insert(bookmark.GetDict());
43
Wei Li0fc6b252016-03-01 16:29:41 -080044 if (bookmark.GetDict() &&
45 bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
Wei Li0e2e5d72016-03-03 11:28:06 -080046 // First check this item.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047 return bookmark;
48 }
Wei Li0e2e5d72016-03-03 11:28:06 -080049
50 // Go into children items.
Lei Zhanga49ef7d2021-04-13 17:37:26 +000051 CPDF_Bookmark child = tree.GetFirstChild(bookmark);
Lei Zhangf245ae62020-05-15 21:49:46 +000052 while (child.GetDict() && !pdfium::Contains(*visited, child.GetDict())) {
Wei Li0e2e5d72016-03-03 11:28:06 -080053 // Check this item and its children.
54 CPDF_Bookmark found = FindBookmark(tree, child, title, visited);
Wei Li0fc6b252016-03-01 16:29:41 -080055 if (found.GetDict())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 return found;
Lei Zhanga49ef7d2021-04-13 17:37:26 +000057 child = tree.GetNextSibling(child);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 }
59 return CPDF_Bookmark();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070060}
61
Lei Zhangbdf72c32015-08-14 19:24:08 -070062CPDF_LinkList* GetLinkList(CPDF_Page* page) {
Lei Zhang8f637632018-05-07 23:36:26 +000063 CPDF_Document* pDoc = page->GetDocument();
Tom Sepezd524d322019-05-28 21:52:27 +000064 auto* pList = static_cast<CPDF_LinkList*>(pDoc->GetLinksContext());
65 if (pList)
66 return pList;
67
Tom Sepez5af95432020-05-15 22:55:16 +000068 auto pNewList = std::make_unique<CPDF_LinkList>();
Tom Sepezd524d322019-05-28 21:52:27 +000069 pList = pNewList.get();
70 pDoc->SetLinksContext(std::move(pNewList));
71 return pList;
Lei Zhangbdf72c32015-08-14 19:24:08 -070072}
73
Dan Sinclair7aba4722018-03-28 17:04:16 +000074} // namespace
Lei Zhangaaed6982018-03-22 18:39:05 +000075
Dan Sinclair00d2ad12017-08-10 14:13:02 -040076FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000077FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -070078 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
79 if (!pDoc)
80 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070081 CPDF_BookmarkTree tree(pDoc);
Andrew Weintraubfe111d92019-06-24 17:19:20 +000082 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
83 return FPDFBookmarkFromCPDFDictionary(
Lei Zhanga49ef7d2021-04-13 17:37:26 +000084 tree.GetFirstChild(cBookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080085}
86
Dan Sinclair00d2ad12017-08-10 14:13:02 -040087FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000088FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -070089 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
90 if (!pDoc)
91 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +000092
Andrew Weintraubfe111d92019-06-24 17:19:20 +000093 if (!bookmark)
Tom Sepez8c628832018-10-09 21:02:15 +000094 return nullptr;
95
Nico Weber9d8ec5a2015-08-04 13:00:21 -070096 CPDF_BookmarkTree tree(pDoc);
Andrew Weintraubfe111d92019-06-24 17:19:20 +000097 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
Tom Sepez525147a2018-05-03 17:19:53 +000098 return FPDFBookmarkFromCPDFDictionary(
Lei Zhanga49ef7d2021-04-13 17:37:26 +000099 tree.GetNextSibling(cBookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -0800100}
101
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400102FPDF_EXPORT unsigned long FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000103FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark,
104 void* buffer,
105 unsigned long buflen) {
106 if (!bookmark)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700107 return 0;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000108 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
109 WideString title = cBookmark.GetTitle();
thestig733e0682016-11-23 05:52:39 -0800110 return Utf16EncodeMaybeCopyAndReturnLength(title, buffer, buflen);
Bo Xu4d62b6b2015-01-10 22:52:59 -0800111}
112
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400113FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
114FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) {
Tom Sepez471a1032015-10-15 16:17:18 -0700115 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
116 if (!pDoc)
117 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000118
Lei Zhangb46a7632019-01-09 02:56:16 +0000119 WideString encodedTitle = WideStringFromFPDFWideString(title);
120 if (encodedTitle.IsEmpty())
Tom Sepez8c628832018-10-09 21:02:15 +0000121 return nullptr;
122
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700123 CPDF_BookmarkTree tree(pDoc);
Lei Zhang5cee3f22018-05-25 21:48:49 +0000124 std::set<const CPDF_Dictionary*> visited;
Tom Sepez525147a2018-05-03 17:19:53 +0000125 return FPDFBookmarkFromCPDFDictionary(
126 FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700127}
128
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000129FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
130FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -0700131 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
132 if (!pDoc)
133 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000134
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000135 if (!bookmark)
Tom Sepez8c628832018-10-09 21:02:15 +0000136 return nullptr;
137
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000138 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
139 CPDF_Dest dest = cBookmark.GetDest(pDoc);
Lei Zhang76525c42018-08-27 18:57:36 +0000140 if (dest.GetArray())
141 return FPDFDestFromCPDFArray(dest.GetArray());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700142 // If this bookmark is not directly associated with a dest, we try to get
143 // action
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000144 CPDF_Action action = cBookmark.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800145 if (!action.GetDict())
Tom Sepez471a1032015-10-15 16:17:18 -0700146 return nullptr;
Lei Zhang76525c42018-08-27 18:57:36 +0000147 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700148}
149
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400150FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000151FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark) {
152 if (!bookmark)
thestig1cd352e2016-06-07 17:53:06 -0700153 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000154
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000155 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
156 return FPDFActionFromCPDFDictionary(cBookmark.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700157}
158
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000159FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION action) {
160 if (!action)
Lei Zhange0947b32015-09-17 14:51:48 -0700161 return PDFACTION_UNSUPPORTED;
162
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000163 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
Lei Zhang7f195a12021-04-13 18:56:36 +0000164 switch (cAction.GetType()) {
165 case CPDF_Action::Type::kGoTo:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166 return PDFACTION_GOTO;
Lei Zhang7f195a12021-04-13 18:56:36 +0000167 case CPDF_Action::Type::kGoToR:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700168 return PDFACTION_REMOTEGOTO;
Lei Zhang7f195a12021-04-13 18:56:36 +0000169 case CPDF_Action::Type::kGoToE:
Zhouhan Chenb70f99d2020-08-08 00:21:07 +0000170 return PDFACTION_EMBEDDEDGOTO;
Lei Zhang7f195a12021-04-13 18:56:36 +0000171 case CPDF_Action::Type::kURI:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700172 return PDFACTION_URI;
Lei Zhang7f195a12021-04-13 18:56:36 +0000173 case CPDF_Action::Type::kLaunch:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 return PDFACTION_LAUNCH;
175 default:
176 return PDFACTION_UNSUPPORTED;
177 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700178}
179
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400180FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFAction_GetDest(FPDF_DOCUMENT document,
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000181 FPDF_ACTION action) {
Tom Sepez471a1032015-10-15 16:17:18 -0700182 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
183 if (!pDoc)
184 return nullptr;
Tom Sepez7bf81642018-10-10 17:27:33 +0000185
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000186 unsigned long type = FPDFAction_GetType(action);
Zhouhan Chenb70f99d2020-08-08 00:21:07 +0000187 if (type != PDFACTION_GOTO && type != PDFACTION_REMOTEGOTO &&
188 type != PDFACTION_EMBEDDEDGOTO) {
Tom Sepez7bf81642018-10-10 17:27:33 +0000189 return nullptr;
Zhouhan Chenb70f99d2020-08-08 00:21:07 +0000190 }
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000191 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
192 return FPDFDestFromCPDFArray(cAction.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700193}
194
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400195FPDF_EXPORT unsigned long FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000196FPDFAction_GetFilePath(FPDF_ACTION action, void* buffer, unsigned long buflen) {
197 unsigned long type = FPDFAction_GetType(action);
Zhouhan Chenb70f99d2020-08-08 00:21:07 +0000198 if (type != PDFACTION_REMOTEGOTO && type != PDFACTION_EMBEDDEDGOTO &&
199 type != PDFACTION_LAUNCH) {
Lei Zhange0947b32015-09-17 14:51:48 -0700200 return 0;
Zhouhan Chenb70f99d2020-08-08 00:21:07 +0000201 }
Lei Zhange0947b32015-09-17 14:51:48 -0700202
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000203 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
204 ByteString path = cAction.GetFilePath().ToUTF8();
Daniel Hosseinian5bc1f982020-04-14 01:05:27 +0000205 return NulTerminateMaybeCopyAndReturnLength(path, buffer, buflen);
Lei Zhange0947b32015-09-17 14:51:48 -0700206}
207
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400208FPDF_EXPORT unsigned long FPDF_CALLCONV
209FPDFAction_GetURIPath(FPDF_DOCUMENT document,
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000210 FPDF_ACTION action,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400211 void* buffer,
212 unsigned long buflen) {
Tom Sepez471a1032015-10-15 16:17:18 -0700213 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
214 if (!pDoc)
215 return 0;
Tom Sepez7bf81642018-10-10 17:27:33 +0000216
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000217 unsigned long type = FPDFAction_GetType(action);
Tom Sepez7bf81642018-10-10 17:27:33 +0000218 if (type != PDFACTION_URI)
219 return 0;
220
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000221 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
222 ByteString path = cAction.GetURI(pDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223 unsigned long len = path.GetLength() + 1;
thestig9067fd62016-11-23 14:10:06 -0800224 if (buffer && len <= buflen)
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400225 memcpy(buffer, path.c_str(), len);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 return len;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700227}
228
Henrique Nakashimae899dd72018-02-01 19:17:04 +0000229FPDF_EXPORT int FPDF_CALLCONV FPDFDest_GetDestPageIndex(FPDF_DOCUMENT document,
Lei Zhangaca3efc2018-03-16 20:27:04 +0000230 FPDF_DEST dest) {
Henrique Nakashima71a7d372018-02-01 17:07:13 +0000231 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
232 if (!pDoc)
233 return -1;
234
Tom Sepez69c32852018-10-09 21:42:39 +0000235 if (!dest)
236 return -1;
237
Tom Sepez525147a2018-05-03 17:19:53 +0000238 CPDF_Dest destination(CPDFArrayFromFPDFDest(dest));
Lei Zhangaca3efc2018-03-16 20:27:04 +0000239 return destination.GetDestPageIndex(pDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700240}
241
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500242FPDF_EXPORT unsigned long FPDF_CALLCONV
Lei Zhang537d3a62019-12-13 17:39:38 +0000243FPDFDest_GetView(FPDF_DEST dest, unsigned long* pNumParams, FS_FLOAT* pParams) {
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000244 if (!dest) {
Lei Zhang326c38c2018-01-10 20:10:05 +0000245 *pNumParams = 0;
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500246 return 0;
247 }
248
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000249 CPDF_Dest destination(CPDFArrayFromFPDFDest(dest));
Lei Zhang11767d32018-03-21 18:59:44 +0000250 unsigned long nParams = destination.GetNumParams();
Tom Sepez9c78c0d2021-01-27 20:13:14 +0000251 DCHECK(nParams <= 4);
Lei Zhang326c38c2018-01-10 20:10:05 +0000252 *pNumParams = nParams;
253 for (unsigned long i = 0; i < nParams; ++i)
Lei Zhang11767d32018-03-21 18:59:44 +0000254 pParams[i] = destination.GetParam(i);
255 return destination.GetZoomMode();
Henrique Nakashimade3f3fc2018-01-04 11:54:18 -0500256}
257
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400258FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000259FPDFDest_GetLocationInPage(FPDF_DEST dest,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400260 FPDF_BOOL* hasXVal,
261 FPDF_BOOL* hasYVal,
262 FPDF_BOOL* hasZoomVal,
263 FS_FLOAT* x,
264 FS_FLOAT* y,
265 FS_FLOAT* zoom) {
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000266 if (!dest)
dsinclairc59fa882016-11-08 06:55:40 -0800267 return false;
268
Tom Sepez5af95432020-05-15 22:55:16 +0000269 auto destination = std::make_unique<CPDF_Dest>(CPDFArrayFromFPDFDest(dest));
dsinclairc59fa882016-11-08 06:55:40 -0800270
271 // FPDF_BOOL is an int, GetXYZ expects bools.
272 bool bHasX;
273 bool bHasY;
274 bool bHasZoom;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000275 if (!destination->GetXYZ(&bHasX, &bHasY, &bHasZoom, x, y, zoom))
dsinclairc59fa882016-11-08 06:55:40 -0800276 return false;
277
278 *hasXVal = bHasX;
279 *hasYVal = bHasY;
280 *hasZoomVal = bHasZoom;
281 return true;
282}
283
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400284FPDF_EXPORT FPDF_LINK FPDF_CALLCONV FPDFLink_GetLinkAtPoint(FPDF_PAGE page,
285 double x,
286 double y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700287 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700288 if (!pPage)
289 return nullptr;
290
291 CPDF_LinkList* pLinkList = GetLinkList(pPage);
292 if (!pLinkList)
293 return nullptr;
294
Tom Sepez525147a2018-05-03 17:19:53 +0000295 CPDF_Link link = pLinkList->GetLinkAtPoint(
296 pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)), nullptr);
297
298 return FPDFLinkFromCPDFDictionary(link.GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700299}
300
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400301FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetLinkZOrderAtPoint(FPDF_PAGE page,
302 double x,
303 double y) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700304 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700305 if (!pPage)
Lei Zhangbdf72c32015-08-14 19:24:08 -0700306 return -1;
307
308 CPDF_LinkList* pLinkList = GetLinkList(pPage);
309 if (!pLinkList)
310 return -1;
311
312 int z_order = -1;
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500313 pLinkList->GetLinkAtPoint(
Dan Sinclair05df0752017-03-14 14:43:42 -0400314 pPage, CFX_PointF(static_cast<float>(x), static_cast<float>(y)),
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500315 &z_order);
Lei Zhangbdf72c32015-08-14 19:24:08 -0700316 return z_order;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700317}
318
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400319FPDF_EXPORT FPDF_DEST FPDF_CALLCONV FPDFLink_GetDest(FPDF_DOCUMENT document,
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000320 FPDF_LINK link) {
321 if (!link)
Lei Zhange0947b32015-09-17 14:51:48 -0700322 return nullptr;
Tom Sepez471a1032015-10-15 16:17:18 -0700323 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
324 if (!pDoc)
325 return nullptr;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000326 CPDF_Link cLink(CPDFDictionaryFromFPDFLink(link));
327 FPDF_DEST dest = FPDFDestFromCPDFArray(cLink.GetDest(pDoc).GetArray());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700328 if (dest)
329 return dest;
330 // If this link is not directly associated with a dest, we try to get action
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000331 CPDF_Action action = cLink.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800332 if (!action.GetDict())
Lei Zhange0947b32015-09-17 14:51:48 -0700333 return nullptr;
Lei Zhang76525c42018-08-27 18:57:36 +0000334 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700335}
336
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000337FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDFLink_GetAction(FPDF_LINK link) {
338 if (!link)
Lei Zhange0947b32015-09-17 14:51:48 -0700339 return nullptr;
340
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000341 CPDF_Link cLink(CPDFDictionaryFromFPDFLink(link));
342 return FPDFActionFromCPDFDictionary(cLink.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700343}
344
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400345FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page,
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000346 int* start_pos,
347 FPDF_LINK* link_annot) {
348 if (!start_pos || !link_annot)
tsepez4cf55152016-11-02 14:37:54 -0700349 return false;
Tom Sepezdb0be962015-10-16 14:00:21 -0700350 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhang197d4982019-08-09 21:40:49 +0000351 if (!pPage)
tsepez4cf55152016-11-02 14:37:54 -0700352 return false;
Henrique Nakashima888af472018-06-07 19:43:42 +0000353 CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700354 if (!pAnnots)
tsepez4cf55152016-11-02 14:37:54 -0700355 return false;
Lei Zhangf40380f2018-10-12 18:31:51 +0000356 for (size_t i = *start_pos; i < pAnnots->size(); i++) {
Lei Zhang11767d32018-03-21 18:59:44 +0000357 CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i));
Dan Sinclairf1251c12015-10-20 16:24:45 -0400358 if (!pDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700359 continue;
dsinclair38fd8442016-09-15 10:15:32 -0700360 if (pDict->GetStringFor("Subtype") == "Link") {
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000361 *start_pos = static_cast<int>(i + 1);
Tom Sepez525147a2018-05-03 17:19:53 +0000362 *link_annot = FPDFLinkFromCPDFDictionary(pDict);
tsepez4cf55152016-11-02 14:37:54 -0700363 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700364 }
365 }
tsepez4cf55152016-11-02 14:37:54 -0700366 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700367}
368
Virender Singhceea6072020-06-18 20:31:25 +0000369FPDF_EXPORT FPDF_ANNOTATION FPDF_CALLCONV
370FPDFLink_GetAnnot(FPDF_PAGE page, FPDF_LINK link_annot) {
371 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
372 CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFLink(link_annot);
373 if (!pPage || !pAnnotDict)
374 return nullptr;
375
376 auto pAnnotContext = std::make_unique<CPDF_AnnotContext>(
377 pAnnotDict, IPDFPageFromFPDFPage(page));
378
379 // Caller takes the ownership of the object.
380 return FPDFAnnotationFromCPDFAnnotContext(pAnnotContext.release());
381}
382
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000383FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK link_annot,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400384 FS_RECTF* rect) {
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000385 if (!link_annot || !rect)
tsepez4cf55152016-11-02 14:37:54 -0700386 return false;
Lei Zhang3567c612019-11-18 18:10:02 +0000387
Lei Zhang11767d32018-03-21 18:59:44 +0000388 CPDF_Dictionary* pAnnotDict = CPDFDictionaryFromFPDFLink(link_annot);
Lei Zhang8da98232019-12-11 23:29:33 +0000389 *rect = FSRectFFromCFXFloatRect(pAnnotDict->GetRectFor("Rect"));
tsepez4cf55152016-11-02 14:37:54 -0700390 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700391}
392
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000393FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK link_annot) {
Lei Zhangaaed6982018-03-22 18:39:05 +0000394 const CPDF_Array* pArray =
395 GetQuadPointsArrayFromDictionary(CPDFDictionaryFromFPDFLink(link_annot));
Lei Zhangf40380f2018-10-12 18:31:51 +0000396 return pArray ? static_cast<int>(pArray->size() / 8) : 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700397}
398
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400399FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
Lei Zhangc3cffbe2018-03-21 13:37:46 +0000400FPDFLink_GetQuadPoints(FPDF_LINK link_annot,
401 int quad_index,
402 FS_QUADPOINTSF* quad_points) {
Lei Zhangaaed6982018-03-22 18:39:05 +0000403 if (!quad_points || quad_index < 0)
tsepez4cf55152016-11-02 14:37:54 -0700404 return false;
Ralf Sippl16381792018-04-12 21:20:26 +0000405
Lei Zhangeda4e7a2019-03-22 21:26:24 +0000406 const CPDF_Dictionary* pLinkDict = CPDFDictionaryFromFPDFLink(link_annot);
Ralf Sippl16381792018-04-12 21:20:26 +0000407 if (!pLinkDict)
408 return false;
409
410 const CPDF_Array* pArray = GetQuadPointsArrayFromDictionary(pLinkDict);
411 if (!pArray)
412 return false;
413
414 return GetQuadPointsAtIndex(pArray, static_cast<size_t>(quad_index),
415 quad_points);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700416}
417
Zhouhan Chen16760b52020-08-12 05:14:00 +0000418FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV FPDF_GetPageAAction(FPDF_PAGE page,
419 int aa_type) {
420 CPDF_Page* pdf_page = CPDFPageFromFPDFPage(page);
421 if (!pdf_page)
422 return nullptr;
423
424 CPDF_Dictionary* page_dict = pdf_page->GetDict();
425 CPDF_AAction aa(page_dict->GetDictFor(pdfium::form_fields::kAA));
426
427 CPDF_AAction::AActionType type;
428 if (aa_type == FPDFPAGE_AACTION_OPEN)
429 type = CPDF_AAction::kOpenPage;
430 else if (aa_type == FPDFPAGE_AACTION_CLOSE)
431 type = CPDF_AAction::kClosePage;
432 else
433 return nullptr;
434
435 if (!aa.ActionExist(type))
436 return nullptr;
437
438 CPDF_Action action = aa.GetAction(type);
439 return FPDFActionFromCPDFDictionary(action.GetDict());
440}
441
Daniel Hosseinianf2e36012020-04-14 02:40:57 +0000442FPDF_EXPORT unsigned long FPDF_CALLCONV
443FPDF_GetFileIdentifier(FPDF_DOCUMENT document,
444 FPDF_FILEIDTYPE id_type,
445 void* buffer,
446 unsigned long buflen) {
447 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
448 if (!pDoc)
449 return 0;
450
451 // Check if |id_type| is valid.
452 if (id_type != FILEIDTYPE_PERMANENT && id_type != FILEIDTYPE_CHANGING)
453 return 0;
454
455 const CPDF_Array* pFileId = pDoc->GetFileIdentifier();
456 if (!pFileId)
457 return 0;
458
459 size_t nIndex = id_type == FILEIDTYPE_PERMANENT ? 0 : 1;
460 const CPDF_String* pValue = ToString(pFileId->GetDirectObjectAt(nIndex));
461 if (!pValue)
462 return 0;
463
464 return NulTerminateMaybeCopyAndReturnLength(pValue->GetString(), buffer,
465 buflen);
466}
467
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400468FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetMetaText(FPDF_DOCUMENT document,
469 FPDF_BYTESTRING tag,
470 void* buffer,
471 unsigned long buflen) {
Tom Sepez471a1032015-10-15 16:17:18 -0700472 if (!tag)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 return 0;
thestig733e0682016-11-23 05:52:39 -0800474 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
Tom Sepez471a1032015-10-15 16:17:18 -0700475 if (!pDoc)
476 return 0;
Artem Strygina3270302018-06-22 12:45:14 +0000477
Lei Zhang01581062017-08-30 14:19:26 -0700478 const CPDF_Dictionary* pInfo = pDoc->GetInfo();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700479 if (!pInfo)
480 return 0;
Ryan Harrison275e2602017-09-18 14:23:18 -0400481 WideString text = pInfo->GetUnicodeTextFor(tag);
thestig733e0682016-11-23 05:52:39 -0800482 return Utf16EncodeMaybeCopyAndReturnLength(text, buffer, buflen);
483}
484
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400485FPDF_EXPORT unsigned long FPDF_CALLCONV
486FPDF_GetPageLabel(FPDF_DOCUMENT document,
487 int page_index,
488 void* buffer,
489 unsigned long buflen) {
thestig733e0682016-11-23 05:52:39 -0800490 if (page_index < 0)
491 return 0;
492
493 // CPDF_PageLabel can deal with NULL |document|.
494 CPDF_PageLabel label(CPDFDocumentFromFPDFDocument(document));
Lei Zhang2c495302021-10-07 23:13:30 +0000495 absl::optional<WideString> str = label.GetLabel(page_index);
Ryan Harrison8eeee772018-01-05 13:39:22 -0500496 return str.has_value()
497 ? Utf16EncodeMaybeCopyAndReturnLength(str.value(), buffer, buflen)
498 : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700499}