blob: 94a1d04cd1b15ee6966d3c68383949c2845ef29f [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"
Wei Li0e2e5d72016-03-03 11:28:06 -080030#include "third_party/base/stl_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070031
Lei Zhangbdf72c32015-08-14 19:24:08 -070032namespace {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070033
Lei Zhangbdf72c32015-08-14 19:24:08 -070034CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree,
35 CPDF_Bookmark bookmark,
Ryan Harrison275e2602017-09-18 14:23:18 -040036 const WideString& title,
Lei Zhang5cee3f22018-05-25 21:48:49 +000037 std::set<const CPDF_Dictionary*>* visited) {
Wei Li0e2e5d72016-03-03 11:28:06 -080038 // Return if already checked to avoid circular calling.
Lei Zhangf245ae62020-05-15 21:49:46 +000039 if (pdfium::Contains(*visited, bookmark.GetDict()))
Wei Li0e2e5d72016-03-03 11:28:06 -080040 return CPDF_Bookmark();
41 visited->insert(bookmark.GetDict());
42
Wei Li0fc6b252016-03-01 16:29:41 -080043 if (bookmark.GetDict() &&
44 bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
Wei Li0e2e5d72016-03-03 11:28:06 -080045 // First check this item.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046 return bookmark;
47 }
Wei Li0e2e5d72016-03-03 11:28:06 -080048
49 // Go into children items.
Tom Sepez22923602019-07-15 21:33:35 +000050 CPDF_Bookmark child = tree.GetFirstChild(&bookmark);
Lei Zhangf245ae62020-05-15 21:49:46 +000051 while (child.GetDict() && !pdfium::Contains(*visited, child.GetDict())) {
Wei Li0e2e5d72016-03-03 11:28:06 -080052 // Check this item and its children.
53 CPDF_Bookmark found = FindBookmark(tree, child, title, visited);
Wei Li0fc6b252016-03-01 16:29:41 -080054 if (found.GetDict())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070055 return found;
Tom Sepez22923602019-07-15 21:33:35 +000056 child = tree.GetNextSibling(&child);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 }
58 return CPDF_Bookmark();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070059}
60
Lei Zhangbdf72c32015-08-14 19:24:08 -070061CPDF_LinkList* GetLinkList(CPDF_Page* page) {
Lei Zhang8f637632018-05-07 23:36:26 +000062 CPDF_Document* pDoc = page->GetDocument();
Tom Sepezd524d322019-05-28 21:52:27 +000063 auto* pList = static_cast<CPDF_LinkList*>(pDoc->GetLinksContext());
64 if (pList)
65 return pList;
66
Tom Sepez5af95432020-05-15 22:55:16 +000067 auto pNewList = std::make_unique<CPDF_LinkList>();
Tom Sepezd524d322019-05-28 21:52:27 +000068 pList = pNewList.get();
69 pDoc->SetLinksContext(std::move(pNewList));
70 return pList;
Lei Zhangbdf72c32015-08-14 19:24:08 -070071}
72
Dan Sinclair7aba4722018-03-28 17:04:16 +000073} // namespace
Lei Zhangaaed6982018-03-22 18:39:05 +000074
Dan Sinclair00d2ad12017-08-10 14:13:02 -040075FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000076FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -070077 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
78 if (!pDoc)
79 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070080 CPDF_BookmarkTree tree(pDoc);
Andrew Weintraubfe111d92019-06-24 17:19:20 +000081 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
82 return FPDFBookmarkFromCPDFDictionary(
Tom Sepez22923602019-07-15 21:33:35 +000083 tree.GetFirstChild(&cBookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080084}
85
Dan Sinclair00d2ad12017-08-10 14:13:02 -040086FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +000087FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -070088 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
89 if (!pDoc)
90 return nullptr;
Tom Sepez525147a2018-05-03 17:19:53 +000091
Andrew Weintraubfe111d92019-06-24 17:19:20 +000092 if (!bookmark)
Tom Sepez8c628832018-10-09 21:02:15 +000093 return nullptr;
94
Nico Weber9d8ec5a2015-08-04 13:00:21 -070095 CPDF_BookmarkTree tree(pDoc);
Andrew Weintraubfe111d92019-06-24 17:19:20 +000096 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
Tom Sepez525147a2018-05-03 17:19:53 +000097 return FPDFBookmarkFromCPDFDictionary(
Tom Sepez22923602019-07-15 21:33:35 +000098 tree.GetNextSibling(&cBookmark).GetDict());
Bo Xu4d62b6b2015-01-10 22:52:59 -080099}
100
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400101FPDF_EXPORT unsigned long FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000102FPDFBookmark_GetTitle(FPDF_BOOKMARK bookmark,
103 void* buffer,
104 unsigned long buflen) {
105 if (!bookmark)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700106 return 0;
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000107 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
108 WideString title = cBookmark.GetTitle();
thestig733e0682016-11-23 05:52:39 -0800109 return Utf16EncodeMaybeCopyAndReturnLength(title, buffer, buflen);
Bo Xu4d62b6b2015-01-10 22:52:59 -0800110}
111
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400112FPDF_EXPORT FPDF_BOOKMARK FPDF_CALLCONV
113FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) {
Tom Sepez471a1032015-10-15 16:17:18 -0700114 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
115 if (!pDoc)
116 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000117
Lei Zhangb46a7632019-01-09 02:56:16 +0000118 WideString encodedTitle = WideStringFromFPDFWideString(title);
119 if (encodedTitle.IsEmpty())
Tom Sepez8c628832018-10-09 21:02:15 +0000120 return nullptr;
121
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700122 CPDF_BookmarkTree tree(pDoc);
Lei Zhang5cee3f22018-05-25 21:48:49 +0000123 std::set<const CPDF_Dictionary*> visited;
Tom Sepez525147a2018-05-03 17:19:53 +0000124 return FPDFBookmarkFromCPDFDictionary(
125 FindBookmark(tree, CPDF_Bookmark(), encodedTitle, &visited).GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700126}
127
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000128FPDF_EXPORT FPDF_DEST FPDF_CALLCONV
129FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) {
Tom Sepez471a1032015-10-15 16:17:18 -0700130 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
131 if (!pDoc)
132 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000133
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000134 if (!bookmark)
Tom Sepez8c628832018-10-09 21:02:15 +0000135 return nullptr;
136
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000137 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
138 CPDF_Dest dest = cBookmark.GetDest(pDoc);
Lei Zhang76525c42018-08-27 18:57:36 +0000139 if (dest.GetArray())
140 return FPDFDestFromCPDFArray(dest.GetArray());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700141 // If this bookmark is not directly associated with a dest, we try to get
142 // action
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000143 CPDF_Action action = cBookmark.GetAction();
Wei Li0fc6b252016-03-01 16:29:41 -0800144 if (!action.GetDict())
Tom Sepez471a1032015-10-15 16:17:18 -0700145 return nullptr;
Lei Zhang76525c42018-08-27 18:57:36 +0000146 return FPDFDestFromCPDFArray(action.GetDest(pDoc).GetArray());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700147}
148
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400149FPDF_EXPORT FPDF_ACTION FPDF_CALLCONV
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000150FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark) {
151 if (!bookmark)
thestig1cd352e2016-06-07 17:53:06 -0700152 return nullptr;
Tom Sepez8c628832018-10-09 21:02:15 +0000153
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000154 CPDF_Bookmark cBookmark(CPDFDictionaryFromFPDFBookmark(bookmark));
155 return FPDFActionFromCPDFDictionary(cBookmark.GetAction().GetDict());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700156}
157
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000158FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFAction_GetType(FPDF_ACTION action) {
159 if (!action)
Lei Zhange0947b32015-09-17 14:51:48 -0700160 return PDFACTION_UNSUPPORTED;
161
Andrew Weintraubfe111d92019-06-24 17:19:20 +0000162 CPDF_Action cAction(CPDFDictionaryFromFPDFAction(action));
163 CPDF_Action::ActionType type = cAction.GetType();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700164 switch (type) {
165 case CPDF_Action::GoTo:
166 return PDFACTION_GOTO;
167 case CPDF_Action::GoToR:
168 return PDFACTION_REMOTEGOTO;
Zhouhan Chenb70f99d2020-08-08 00:21:07 +0000169 case CPDF_Action::GoToE:
170 return PDFACTION_EMBEDDEDGOTO;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171 case CPDF_Action::URI:
172 return PDFACTION_URI;
173 case CPDF_Action::Launch:
174 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();
Lei Zhang326c38c2018-01-10 20:10:05 +0000251 ASSERT(nParams <= 4);
252 *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));
Ryan Harrison8eeee772018-01-05 13:39:22 -0500495 Optional<WideString> str = label.GetLabel(page_index);
496 return str.has_value()
497 ? Utf16EncodeMaybeCopyAndReturnLength(str.value(), buffer, buflen)
498 : 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700499}