Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/pdf/xpdf/Link.cc
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/xpdf/Link.cc')
-rw-r--r--pdf/xpdf/Link.cc279
1 files changed, 192 insertions, 87 deletions
diff --git a/pdf/xpdf/Link.cc b/pdf/xpdf/Link.cc
index eb9d033..b16563a 100644
--- a/pdf/xpdf/Link.cc
+++ b/pdf/xpdf/Link.cc
@@ -6,11 +6,12 @@
//
//========================================================================
-#ifdef __GNUC__
+#include <aconf.h>
+
+#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
-#include <aconf.h>
#include <stddef.h>
#include <string.h>
#include "gmem.h"
@@ -22,8 +23,117 @@
#include "Link.h"
//------------------------------------------------------------------------
+// LinkAction
+//------------------------------------------------------------------------
+
+LinkAction *LinkAction::parseDest(Object *obj) {
+ LinkAction *action;
+
+ action = new LinkGoTo(obj);
+ if (!action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
+ LinkAction *action;
+ Object obj2, obj3, obj4;
+
+ if (!obj->isDict()) {
+ error(-1, "Bad annotation action");
+ return NULL;
+ }
+
+ obj->dictLookup("S", &obj2);
+
+ // GoTo action
+ if (obj2.isName("GoTo")) {
+ obj->dictLookup("D", &obj3);
+ action = new LinkGoTo(&obj3);
+ obj3.free();
+
+ // GoToR action
+ } else if (obj2.isName("GoToR")) {
+ obj->dictLookup("F", &obj3);
+ obj->dictLookup("D", &obj4);
+ action = new LinkGoToR(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // Launch action
+ } else if (obj2.isName("Launch")) {
+ action = new LinkLaunch(obj);
+
+ // URI action
+ } else if (obj2.isName("URI")) {
+ obj->dictLookup("URI", &obj3);
+ action = new LinkURI(&obj3, baseURI);
+ obj3.free();
+
+ // Named action
+ } else if (obj2.isName("Named")) {
+ obj->dictLookup("N", &obj3);
+ action = new LinkNamed(&obj3);
+ obj3.free();
+
+ // Movie action
+ } else if (obj2.isName("Movie")) {
+ obj->dictLookupNF("Annot", &obj3);
+ obj->dictLookup("T", &obj4);
+ action = new LinkMovie(&obj3, &obj4);
+ obj3.free();
+ obj4.free();
+
+ // unknown action
+ } else if (obj2.isName()) {
+ action = new LinkUnknown(obj2.getName());
+
+ // action is missing or wrong type
+ } else {
+ error(-1, "Bad annotation action");
+ action = NULL;
+ }
-static GString *getFileSpecName(Object *fileSpecObj);
+ obj2.free();
+
+ if (action && !action->isOk()) {
+ delete action;
+ return NULL;
+ }
+ return action;
+}
+
+GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
+ GString *name;
+ Object obj1;
+
+ name = NULL;
+
+ // string
+ if (fileSpecObj->isString()) {
+ name = fileSpecObj->getString()->copy();
+
+ // dictionary
+ } else if (fileSpecObj->isDict()) {
+ if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
+ obj1.free();
+ fileSpecObj->dictLookup("F", &obj1);
+ }
+ if (obj1.isString())
+ name = obj1.getString()->copy();
+ else
+ error(-1, "Illegal file spec in link");
+ obj1.free();
+
+ // error
+ } else {
+ error(-1, "Illegal file spec in link");
+ }
+
+ return name;
+}
//------------------------------------------------------------------------
// LinkDest
@@ -37,6 +147,10 @@ LinkDest::LinkDest(Array *a) {
ok = gFalse;
// get page
+ if (a->getLength() < 2) {
+ error(-1, "Annotation destination array has wrong length");
+ return;
+ }
a->getNF(0, &obj1);
if (obj1.isInt()) {
pageNum = obj1.getInt() + 1;
@@ -56,6 +170,10 @@ LinkDest::LinkDest(Array *a) {
// XYZ link
if (obj1.isName("XYZ")) {
+ if (a->getLength() != 5) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destXYZ;
a->get(2, &obj2);
if (obj2.isNull()) {
@@ -93,10 +211,18 @@ LinkDest::LinkDest(Array *a) {
// Fit link
} else if (obj1.isName("Fit")) {
+ if (a->getLength() != 2) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFit;
// FitH link
} else if (obj1.isName("FitH")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -107,6 +233,10 @@ LinkDest::LinkDest(Array *a) {
// FitV link
} else if (obj1.isName("FitV")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -117,6 +247,10 @@ LinkDest::LinkDest(Array *a) {
// FitR link
} else if (obj1.isName("FitR")) {
+ if (a->getLength() != 6) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitR;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -145,10 +279,18 @@ LinkDest::LinkDest(Array *a) {
// FitB link
} else if (obj1.isName("FitB")) {
+ if (a->getLength() != 2) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitB;
// FitBH link
} else if (obj1.isName("FitBH")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitBH;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -159,6 +301,10 @@ LinkDest::LinkDest(Array *a) {
// FitBV link
} else if (obj1.isName("FitBV")) {
+ if (a->getLength() != 3) {
+ error(-1, "Annotation destination array has wrong length");
+ goto err2;
+ }
kind = destFitBV;
if (!a->get(2, &obj2)->isNum()) {
error(-1, "Bad annotation destination position");
@@ -292,18 +438,33 @@ LinkLaunch::LinkLaunch(Object *actionObj) {
fileName = getFileSpecName(&obj1);
} else {
obj1.free();
+#ifdef WIN32
+ if (actionObj->dictLookup("Win", &obj1)->isDict()) {
+ obj1.dictLookup("F", &obj2);
+ fileName = getFileSpecName(&obj2);
+ obj2.free();
+ if (obj1.dictLookup("P", &obj2)->isString()) {
+ params = obj2.getString()->copy();
+ }
+ obj2.free();
+ } else {
+ error(-1, "Bad launch-type link action");
+ }
+#else
//~ This hasn't been defined by Adobe yet, so assume it looks
//~ just like the Win dictionary until they say otherwise.
if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
obj1.dictLookup("F", &obj2);
fileName = getFileSpecName(&obj2);
obj2.free();
- if (obj1.dictLookup("P", &obj2)->isString())
+ if (obj1.dictLookup("P", &obj2)->isString()) {
params = obj2.getString()->copy();
+ }
obj2.free();
} else {
error(-1, "Bad launch-type link action");
}
+#endif
}
obj1.free();
}
@@ -378,6 +539,28 @@ LinkNamed::~LinkNamed() {
}
//------------------------------------------------------------------------
+// LinkMovie
+//------------------------------------------------------------------------
+
+LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
+ annotRef.num = -1;
+ title = NULL;
+ if (annotObj->isRef()) {
+ annotRef = annotObj->getRef();
+ } else if (titleObj->isString()) {
+ title = titleObj->getString()->copy();
+ } else {
+ error(-1, "Movie action is missing both the Annot and T keys");
+ }
+}
+
+LinkMovie::~LinkMovie() {
+ if (title) {
+ delete title;
+ }
+}
+
+//------------------------------------------------------------------------
// LinkUnknown
//------------------------------------------------------------------------
@@ -394,7 +577,7 @@ LinkUnknown::~LinkUnknown() {
//------------------------------------------------------------------------
Link::Link(Dict *dict, GString *baseURI) {
- Object obj1, obj2, obj3, obj4;
+ Object obj1, obj2;
double t;
action = NULL;
@@ -457,66 +640,21 @@ Link::Link(Dict *dict, GString *baseURI) {
// look for destination
if (!dict->lookup("Dest", &obj1)->isNull()) {
- action = new LinkGoTo(&obj1);
+ action = LinkAction::parseDest(&obj1);
// look for action
} else {
obj1.free();
if (dict->lookup("A", &obj1)->isDict()) {
- obj1.dictLookup("S", &obj2);
-
- // GoTo action
- if (obj2.isName("GoTo")) {
- obj1.dictLookup("D", &obj3);
- action = new LinkGoTo(&obj3);
- obj3.free();
-
- // GoToR action
- } else if (obj2.isName("GoToR")) {
- obj1.dictLookup("F", &obj3);
- obj1.dictLookup("D", &obj4);
- action = new LinkGoToR(&obj3, &obj4);
- obj3.free();
- obj4.free();
-
- // Launch action
- } else if (obj2.isName("Launch")) {
- action = new LinkLaunch(&obj1);
-
- // URI action
- } else if (obj2.isName("URI")) {
- obj1.dictLookup("URI", &obj3);
- action = new LinkURI(&obj3, baseURI);
- obj3.free();
-
- // Named action
- } else if (obj2.isName("Named")) {
- obj1.dictLookup("N", &obj3);
- action = new LinkNamed(&obj3);
- obj3.free();
-
- // unknown action
- } else if (obj2.isName()) {
- action = new LinkUnknown(obj2.getName());
-
- // action is missing or wrong type
- } else {
- error(-1, "Bad annotation action");
- action = NULL;
- }
-
- obj2.free();
-
- } else {
- error(-1, "Missing annotation destination/action");
- action = NULL;
+ action = LinkAction::parseAction(&obj1, baseURI);
}
}
obj1.free();
// check for bad action
- if (action && action->isOk())
+ if (action) {
ok = gTrue;
+ }
return;
@@ -595,36 +733,3 @@ GBool Links::onLink(double x, double y) const {
}
return gFalse;
}
-
-//------------------------------------------------------------------------
-
-// Extract a file name from a file specification (string or dictionary).
-static GString *getFileSpecName(Object *fileSpecObj) {
- GString *name;
- Object obj1;
-
- name = NULL;
-
- // string
- if (fileSpecObj->isString()) {
- name = fileSpecObj->getString()->copy();
-
- // dictionary
- } else if (fileSpecObj->isDict()) {
- if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
- obj1.free();
- fileSpecObj->dictLookup("F", &obj1);
- }
- if (obj1.isString())
- name = obj1.getString()->copy();
- else
- error(-1, "Illegal file spec in link");
- obj1.free();
-
- // error
- } else {
- error(-1, "Illegal file spec in link");
- }
-
- return name;
-}