1//========================================================================
2//
3// Link.h
4//
5// Copyright 1996-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2006, 2008 Pino Toscano <pino@kde.org>
17// Copyright (C) 2008 Hugo Mercier <hmercier31@gmail.com>
18// Copyright (C) 2010, 2011 Carlos Garcia Campos <carlosgc@gnome.org>
19// Copyright (C) 2012 Tobias Koening <tobias.koenig@kdab.com>
20// Copyright (C) 2018-2023 Albert Astals Cid <aacid@kde.org>
21// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
22// Copyright (C) 2018 Intevation GmbH <intevation@intevation.de>
23// Copyright (C) 2019, 2020 Oliver Sander <oliver.sander@tu-dresden.de>
24// Copyright (C) 2020 Adam Reichold <adam.reichold@t-online.de>
25// Copyright (C) 2020 Marek Kasik <mkasik@redhat.com>
26//
27// To see a description of the changes please see the Changelog file that
28// came with your tarball or type make ChangeLog if you are building from git
29//
30//========================================================================
31
32#ifndef LINK_H
33#define LINK_H
34
35#include "Object.h"
36#include "poppler_private_export.h"
37#include <memory>
38#include <optional>
39#include <set>
40
41class GooString;
42class Array;
43class Dict;
44class Sound;
45class MediaRendition;
46class AnnotLink;
47class Annots;
48
49//------------------------------------------------------------------------
50// LinkAction
51//------------------------------------------------------------------------
52
53enum LinkActionKind
54{
55 actionGoTo, // go to destination
56 actionGoToR, // go to destination in new file
57 actionLaunch, // launch app (or open document)
58 actionURI, // URI
59 actionNamed, // named action
60 actionMovie, // movie action
61 actionRendition, // rendition action
62 actionSound, // sound action
63 actionJavaScript, // JavaScript action
64 actionOCGState, // Set-OCG-State action
65 actionHide, // Hide action
66 actionResetForm, // ResetForm action
67 actionUnknown // anything else
68};
69
70class POPPLER_PRIVATE_EXPORT LinkAction
71{
72public:
73 LinkAction();
74 LinkAction(const LinkAction &) = delete;
75 LinkAction &operator=(const LinkAction &other) = delete;
76
77 // Destructor.
78 virtual ~LinkAction();
79
80 // Was the LinkAction created successfully?
81 virtual bool isOk() const = 0;
82
83 // Check link action type.
84 virtual LinkActionKind getKind() const = 0;
85
86 // Parse a destination (old-style action) name, string, or array.
87 static std::unique_ptr<LinkAction> parseDest(const Object *obj);
88
89 // Parse an action dictionary.
90 static std::unique_ptr<LinkAction> parseAction(const Object *obj, const std::optional<std::string> &baseURI = {});
91
92 // A List of the next actions to execute in order.
93 const std::vector<std::unique_ptr<LinkAction>> &nextActions() const;
94
95private:
96 static std::unique_ptr<LinkAction> parseAction(const Object *obj, const std::optional<std::string> &baseURI, std::set<int> *seenNextActions);
97
98 std::vector<std::unique_ptr<LinkAction>> nextActionList;
99};
100
101//------------------------------------------------------------------------
102// LinkDest
103//------------------------------------------------------------------------
104
105enum LinkDestKind
106{
107 destXYZ,
108 destFit,
109 destFitH,
110 destFitV,
111 destFitR,
112 destFitB,
113 destFitBH,
114 destFitBV
115};
116
117class POPPLER_PRIVATE_EXPORT LinkDest
118{
119public:
120 // Build a LinkDest from the array.
121 explicit LinkDest(const Array *a);
122
123 // Was the LinkDest created successfully?
124 bool isOk() const { return ok; }
125
126 // Accessors.
127 LinkDestKind getKind() const { return kind; }
128 bool isPageRef() const { return pageIsRef; }
129 int getPageNum() const { return pageNum; }
130 Ref getPageRef() const { return pageRef; }
131 double getLeft() const { return left; }
132 double getBottom() const { return bottom; }
133 double getRight() const { return right; }
134 double getTop() const { return top; }
135 double getZoom() const { return zoom; }
136 bool getChangeLeft() const { return changeLeft; }
137 bool getChangeTop() const { return changeTop; }
138 bool getChangeZoom() const { return changeZoom; }
139
140private:
141 LinkDestKind kind; // destination type
142 bool pageIsRef; // is the page a reference or number?
143 union {
144 Ref pageRef; // reference to page
145 int pageNum; // one-relative page number
146 };
147 double left, bottom; // position
148 double right, top;
149 double zoom; // zoom factor
150 bool changeLeft, changeTop; // which position components to change:
151 bool changeZoom; // destXYZ uses all three;
152 // destFitH/BH use changeTop;
153 // destFitV/BV use changeLeft
154 bool ok; // set if created successfully
155};
156
157//------------------------------------------------------------------------
158// LinkGoTo
159//------------------------------------------------------------------------
160
161class POPPLER_PRIVATE_EXPORT LinkGoTo : public LinkAction
162{
163public:
164 // Build a LinkGoTo from a destination (dictionary, name, or string).
165 explicit LinkGoTo(const Object *destObj);
166
167 ~LinkGoTo() override;
168
169 // Was the LinkGoTo created successfully?
170 bool isOk() const override { return dest || namedDest; }
171
172 // Accessors.
173 LinkActionKind getKind() const override { return actionGoTo; }
174 const LinkDest *getDest() const { return dest.get(); }
175 const GooString *getNamedDest() const { return namedDest.get(); }
176
177private:
178 std::unique_ptr<LinkDest> dest; // regular destination (nullptr for remote
179 // link with bad destination)
180 std::unique_ptr<GooString> namedDest; // named destination (only one of dest and
181 // and namedDest may be non-nullptr)
182};
183
184//------------------------------------------------------------------------
185// LinkGoToR
186//------------------------------------------------------------------------
187
188class LinkGoToR : public LinkAction
189{
190public:
191 // Build a LinkGoToR from a file spec (dictionary) and destination
192 // (dictionary, name, or string).
193 LinkGoToR(Object *fileSpecObj, Object *destObj);
194
195 ~LinkGoToR() override;
196
197 // Was the LinkGoToR created successfully?
198 bool isOk() const override { return fileName && (dest || namedDest); }
199
200 // Accessors.
201 LinkActionKind getKind() const override { return actionGoToR; }
202 const GooString *getFileName() const { return fileName.get(); }
203 const LinkDest *getDest() const { return dest.get(); }
204 const GooString *getNamedDest() const { return namedDest.get(); }
205
206private:
207 std::unique_ptr<GooString> fileName; // file name
208 std::unique_ptr<LinkDest> dest; // regular destination (nullptr for remote
209 // link with bad destination)
210 std::unique_ptr<GooString> namedDest; // named destination (only one of dest and
211 // and namedDest may be non-nullptr)
212};
213
214//------------------------------------------------------------------------
215// LinkLaunch
216//------------------------------------------------------------------------
217
218class LinkLaunch : public LinkAction
219{
220public:
221 // Build a LinkLaunch from an action dictionary.
222 explicit LinkLaunch(const Object *actionObj);
223 ~LinkLaunch() override;
224
225 // Was the LinkLaunch created successfully?
226 bool isOk() const override { return fileName != nullptr; }
227
228 // Accessors.
229 LinkActionKind getKind() const override { return actionLaunch; }
230 const GooString *getFileName() const { return fileName.get(); }
231 const GooString *getParams() const { return params.get(); }
232
233private:
234 std::unique_ptr<GooString> fileName; // file name
235 std::unique_ptr<GooString> params; // parameters
236};
237
238//------------------------------------------------------------------------
239// LinkURI
240//------------------------------------------------------------------------
241
242class POPPLER_PRIVATE_EXPORT LinkURI : public LinkAction
243{
244public:
245 // Build a LinkURI given the URI (string) and base URI.
246 LinkURI(const Object *uriObj, const std::optional<std::string> &baseURI);
247
248 ~LinkURI() override;
249
250 // Was the LinkURI created successfully?
251 bool isOk() const override { return hasURIFlag; }
252
253 // Accessors.
254 LinkActionKind getKind() const override { return actionURI; }
255 const std::string &getURI() const { return uri; }
256
257private:
258 std::string uri; // the URI
259 bool hasURIFlag;
260};
261
262//------------------------------------------------------------------------
263// LinkNamed
264//------------------------------------------------------------------------
265
266class LinkNamed : public LinkAction
267{
268public:
269 // Build a LinkNamed given the action name.
270 explicit LinkNamed(const Object *nameObj);
271
272 ~LinkNamed() override;
273
274 bool isOk() const override { return hasNameFlag; }
275
276 LinkActionKind getKind() const override { return actionNamed; }
277 const std::string &getName() const { return name; }
278
279private:
280 std::string name;
281 bool hasNameFlag;
282};
283
284//------------------------------------------------------------------------
285// LinkMovie
286//------------------------------------------------------------------------
287
288class LinkMovie : public LinkAction
289{
290public:
291 enum OperationType
292 {
293 operationTypePlay,
294 operationTypePause,
295 operationTypeResume,
296 operationTypeStop
297 };
298
299 explicit LinkMovie(const Object *obj);
300
301 ~LinkMovie() override;
302
303 bool isOk() const override { return hasAnnotRef() || hasAnnotTitleFlag; }
304 LinkActionKind getKind() const override { return actionMovie; }
305
306 // a movie action stores either an indirect reference to a movie annotation
307 // or the movie annotation title
308
309 bool hasAnnotRef() const { return annotRef != Ref::INVALID(); }
310 bool hasAnnotTitle() const { return hasAnnotTitleFlag; }
311 const Ref *getAnnotRef() const { return &annotRef; }
312 const std::string &getAnnotTitle() const { return annotTitle; }
313
314 OperationType getOperation() const { return operation; }
315
316private:
317 Ref annotRef; // Annotation
318 std::string annotTitle; // T
319 bool hasAnnotTitleFlag;
320
321 OperationType operation; // Operation
322};
323
324//------------------------------------------------------------------------
325// LinkRendition
326//------------------------------------------------------------------------
327
328class LinkRendition : public LinkAction
329{
330public:
331 /**
332 * Describes the possible rendition operations.
333 */
334 enum RenditionOperation
335 {
336 NoRendition,
337 PlayRendition,
338 StopRendition,
339 PauseRendition,
340 ResumeRendition
341 };
342
343 explicit LinkRendition(const Object *Obj);
344
345 ~LinkRendition() override;
346
347 bool isOk() const override { return true; }
348
349 LinkActionKind getKind() const override { return actionRendition; }
350
351 bool hasScreenAnnot() const { return screenRef != Ref::INVALID(); }
352 Ref getScreenAnnot() const { return screenRef; }
353
354 RenditionOperation getOperation() const { return operation; }
355
356 const MediaRendition *getMedia() const { return media; }
357
358 const std::string &getScript() const { return js; }
359
360private:
361 Ref screenRef;
362 RenditionOperation operation;
363
364 MediaRendition *media;
365
366 std::string js;
367};
368
369//------------------------------------------------------------------------
370// LinkSound
371//------------------------------------------------------------------------
372
373class LinkSound : public LinkAction
374{
375public:
376 explicit LinkSound(const Object *soundObj);
377
378 ~LinkSound() override;
379
380 bool isOk() const override { return sound != nullptr; }
381
382 LinkActionKind getKind() const override { return actionSound; }
383
384 double getVolume() const { return volume; }
385 bool getSynchronous() const { return sync; }
386 bool getRepeat() const { return repeat; }
387 bool getMix() const { return mix; }
388 Sound *getSound() const { return sound.get(); }
389
390private:
391 double volume;
392 bool sync;
393 bool repeat;
394 bool mix;
395 std::unique_ptr<Sound> sound;
396};
397
398//------------------------------------------------------------------------
399// LinkJavaScript
400//------------------------------------------------------------------------
401
402class LinkJavaScript : public LinkAction
403{
404public:
405 // Build a LinkJavaScript given the action name.
406 explicit LinkJavaScript(Object *jsObj);
407
408 ~LinkJavaScript() override;
409
410 bool isOk() const override { return isValid; }
411
412 LinkActionKind getKind() const override { return actionJavaScript; }
413 const std::string &getScript() const { return js; }
414
415 static Object createObject(XRef *xref, const std::string &js);
416
417private:
418 std::string js;
419 bool isValid;
420};
421
422//------------------------------------------------------------------------
423// LinkOCGState
424//------------------------------------------------------------------------
425class LinkOCGState : public LinkAction
426{
427public:
428 explicit LinkOCGState(const Object *obj);
429
430 ~LinkOCGState() override;
431
432 bool isOk() const override { return isValid; }
433
434 LinkActionKind getKind() const override { return actionOCGState; }
435
436 enum State
437 {
438 On,
439 Off,
440 Toggle
441 };
442 struct StateList
443 {
444 StateList() = default;
445 ~StateList() = default;
446 State st;
447 std::vector<Ref> list;
448 };
449
450 const std::vector<StateList> &getStateList() const { return stateList; }
451 bool getPreserveRB() const { return preserveRB; }
452
453private:
454 std::vector<StateList> stateList;
455 bool isValid;
456 bool preserveRB;
457};
458
459//------------------------------------------------------------------------
460// LinkHide
461//------------------------------------------------------------------------
462
463class LinkHide : public LinkAction
464{
465public:
466 explicit LinkHide(const Object *hideObj);
467
468 ~LinkHide() override;
469
470 bool isOk() const override { return hasTargetNameFlag; }
471 LinkActionKind getKind() const override { return actionHide; }
472
473 // According to spec the target can be either:
474 // a) A text string containing the fully qualified name of the target
475 // field.
476 // b) An indirect reference to an annotation dictionary.
477 // c) An array of "such dictionaries or text strings".
478 //
479 // While b / c appear to be very uncommon and can't easily be
480 // created with Adobe Acrobat DC. So only support hide
481 // actions with named targets (yet).
482 bool hasTargetName() const { return hasTargetNameFlag; }
483 const std::string &getTargetName() const { return targetName; }
484
485 // Should this action show or hide.
486 bool isShowAction() const { return show; }
487
488private:
489 bool hasTargetNameFlag;
490 std::string targetName;
491 bool show;
492};
493
494//------------------------------------------------------------------------
495// LinkResetForm
496//------------------------------------------------------------------------
497
498class POPPLER_PRIVATE_EXPORT LinkResetForm : public LinkAction
499{
500public:
501 // Build a LinkResetForm.
502 explicit LinkResetForm(const Object *nameObj);
503
504 ~LinkResetForm() override;
505
506 bool isOk() const override { return true; }
507
508 LinkActionKind getKind() const override { return actionResetForm; }
509
510 const std::vector<std::string> &getFields() const { return fields; }
511 bool getExclude() const { return exclude; }
512
513private:
514 std::vector<std::string> fields;
515 bool exclude;
516};
517
518//------------------------------------------------------------------------
519// LinkUnknown
520//------------------------------------------------------------------------
521
522class LinkUnknown : public LinkAction
523{
524public:
525 // Build a LinkUnknown with the specified action type.
526 explicit LinkUnknown(const char *actionA);
527
528 ~LinkUnknown() override;
529
530 // Was the LinkUnknown create successfully?
531 // Yes: nothing can go wrong when creating LinkUnknown objects
532 bool isOk() const override { return true; }
533
534 // Accessors.
535 LinkActionKind getKind() const override { return actionUnknown; }
536 const std::string &getAction() const { return action; }
537
538private:
539 std::string action; // action subtype
540};
541
542//------------------------------------------------------------------------
543// Links
544//------------------------------------------------------------------------
545
546class POPPLER_PRIVATE_EXPORT Links
547{
548public:
549 // Extract links from array of annotations.
550 explicit Links(Annots *annots);
551
552 // Destructor.
553 ~Links();
554
555 Links(const Links &) = delete;
556 Links &operator=(const Links &) = delete;
557
558 const std::vector<AnnotLink *> &getLinks() const { return links; }
559
560private:
561 std::vector<AnnotLink *> links;
562};
563
564#endif
565

source code of poppler/poppler/Link.h