Coverage Report

Created: 2026-06-10 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xpdf-4.06/xpdf/Link.cc
Line
Count
Source
1
//========================================================================
2
//
3
// Link.cc
4
//
5
// Copyright 1996-2003 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#include <stddef.h>
12
#include <string.h>
13
#include "gmem.h"
14
#include "gmempp.h"
15
#include "GString.h"
16
#include "Error.h"
17
#include "Object.h"
18
#include "Array.h"
19
#include "Dict.h"
20
#include "Link.h"
21
22
//------------------------------------------------------------------------
23
// LinkAction
24
//------------------------------------------------------------------------
25
26
142
LinkAction *LinkAction::parseDest(Object *obj) {
27
142
  LinkAction *action;
28
29
142
  action = new LinkGoTo(obj);
30
142
  if (!action->isOk()) {
31
73
    delete action;
32
73
    return NULL;
33
73
  }
34
69
  return action;
35
142
}
36
37
1.36k
LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
38
1.36k
  LinkAction *action;
39
1.36k
  Object obj2, obj3, obj4, obj5;
40
41
1.36k
  if (!obj->isDict()) {
42
27
    error(errSyntaxWarning, -1, "Bad annotation action");
43
27
    return NULL;
44
27
  }
45
46
1.33k
  obj->dictLookup("S", &obj2);
47
48
  // GoTo action
49
1.33k
  if (obj2.isName("GoTo")) {
50
261
    obj->dictLookup("D", &obj3);
51
261
    action = new LinkGoTo(&obj3);
52
261
    obj3.free();
53
54
  // GoToR action
55
1.07k
  } else if (obj2.isName("GoToR")) {
56
268
    obj->dictLookup("F", &obj3);
57
268
    obj->dictLookup("D", &obj4);
58
268
    action = new LinkGoToR(&obj3, &obj4);
59
268
    obj3.free();
60
268
    obj4.free();
61
62
  // Launch action
63
806
  } else if (obj2.isName("Launch")) {
64
0
    action = new LinkLaunch(obj);
65
66
  // URI action
67
806
  } else if (obj2.isName("URI")) {
68
371
    obj->dictLookup("URI", &obj3);
69
371
    action = new LinkURI(&obj3, baseURI);
70
371
    obj3.free();
71
72
  // Named action
73
435
  } else if (obj2.isName("Named")) {
74
0
    obj->dictLookup("N", &obj3);
75
0
    action = new LinkNamed(&obj3);
76
0
    obj3.free();
77
78
  // Movie action
79
435
  } else if (obj2.isName("Movie")) {
80
0
    obj->dictLookupNF("Annot", &obj3);
81
0
    obj->dictLookup("T", &obj4);
82
0
    action = new LinkMovie(&obj3, &obj4);
83
0
    obj3.free();
84
0
    obj4.free();
85
86
  // JavaScript action
87
435
  } else if (obj2.isName("JavaScript")) {
88
36
    obj->dictLookup("JS", &obj3);
89
36
    action = new LinkJavaScript(&obj3);
90
36
    obj3.free();
91
92
  // SubmitForm action
93
399
  } else if (obj2.isName("SubmitForm")) {
94
0
    obj->dictLookup("F", &obj3);
95
0
    obj->dictLookup("Fields", &obj4);
96
0
    obj->dictLookup("Flags", &obj5);
97
0
    action = new LinkSubmitForm(&obj3, &obj4, &obj5);
98
0
    obj3.free();
99
0
    obj4.free();
100
0
    obj5.free();
101
102
  // Hide action
103
399
  } else if (obj2.isName("Hide")) {
104
0
    obj->dictLookupNF("T", &obj3);
105
0
    obj->dictLookup("H", &obj4);
106
0
    action = new LinkHide(&obj3, &obj4);
107
0
    obj3.free();
108
0
    obj4.free();
109
110
  // unknown action
111
399
  } else if (obj2.isName()) {
112
120
    action = new LinkUnknown(obj2.getName());
113
114
  // action is missing or wrong type
115
279
  } else {
116
279
    error(errSyntaxWarning, -1, "Bad annotation action");
117
279
    action = NULL;
118
279
  }
119
120
1.33k
  obj2.free();
121
122
1.33k
  if (action && !action->isOk()) {
123
411
    delete action;
124
411
    return NULL;
125
411
  }
126
924
  return action;
127
1.33k
}
128
129
268
GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
130
268
  GString *name;
131
268
  Object obj1;
132
133
268
  name = NULL;
134
135
  // string
136
268
  if (fileSpecObj->isString()) {
137
18
    name = fileSpecObj->getString()->copy();
138
139
  // dictionary
140
250
  } else if (fileSpecObj->isDict()) {
141
#ifdef _WIN32
142
    if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) {
143
#else
144
0
    if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
145
0
#endif
146
0
      obj1.free();
147
0
      fileSpecObj->dictLookup("F", &obj1);
148
0
    }
149
0
    if (obj1.isString()) {
150
0
      name = obj1.getString()->copy();
151
0
    } else {
152
0
      error(errSyntaxWarning, -1, "Illegal file spec in link");
153
0
    }
154
0
    obj1.free();
155
156
  // error
157
250
  } else {
158
250
    error(errSyntaxWarning, -1, "Illegal file spec in link");
159
250
  }
160
161
  // system-dependent path manipulation
162
268
  if (name) {
163
#ifdef _WIN32
164
    int i, j;
165
166
    // "//...."             --> "\...."
167
    // "/x/...."            --> "x:\...."
168
    // "/server/share/...." --> "\\server\share\...."
169
    // convert escaped slashes to slashes and unescaped slashes to backslashes
170
    i = 0;
171
    if (name->getChar(0) == '/') {
172
      if (name->getLength() >= 2 && name->getChar(1) == '/') {
173
  name->del(0);
174
  i = 0;
175
      } else if (name->getLength() >= 2 &&
176
     ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') ||
177
      (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) &&
178
     (name->getLength() == 2 || name->getChar(2) == '/')) {
179
  name->setChar(0, name->getChar(1));
180
  name->setChar(1, ':');
181
  i = 2;
182
      } else {
183
  for (j = 2; j < name->getLength(); ++j) {
184
    if (name->getChar(j-1) != '\\' &&
185
        name->getChar(j) == '/') {
186
      break;
187
    }
188
  }
189
  if (j < name->getLength()) {
190
    name->setChar(0, '\\');
191
    name->insert(0, '\\');
192
    i = 2;
193
  }
194
      }
195
    }
196
    for (; i < name->getLength(); ++i) {
197
      if (name->getChar(i) == '/') {
198
  name->setChar(i, '\\');
199
      } else if (name->getChar(i) == '\\' &&
200
     i+1 < name->getLength() &&
201
     name->getChar(i+1) == '/') {
202
  name->del(i);
203
      }
204
    }
205
#else
206
    // no manipulation needed for Unix
207
18
#endif
208
18
  }
209
210
268
  return name;
211
268
}
212
213
//------------------------------------------------------------------------
214
// LinkDest
215
//------------------------------------------------------------------------
216
217
315
LinkDest::LinkDest(Array *a) {
218
315
  Object obj1, obj2;
219
220
  // initialize fields
221
315
  left = bottom = right = top = zoom = 0;
222
315
  ok = gFalse;
223
224
  // get page
225
315
  if (a->getLength() < 2) {
226
8
    error(errSyntaxWarning, -1, "Annotation destination array is too short");
227
8
    return;
228
8
  }
229
307
  a->getNF(0, &obj1);
230
307
  if (obj1.isInt()) {
231
14
    pageNum = obj1.getInt() + 1;
232
14
    pageIsRef = gFalse;
233
293
  } else if (obj1.isRef()) {
234
284
    pageRef.num = obj1.getRefNum();
235
284
    pageRef.gen = obj1.getRefGen();
236
284
    pageIsRef = gTrue;
237
284
  } else {
238
9
    error(errSyntaxWarning, -1, "Bad annotation destination");
239
9
    goto err2;
240
9
  }
241
298
  obj1.free();
242
243
  // get destination type
244
298
  a->get(1, &obj1);
245
246
  // XYZ link
247
298
  if (obj1.isName("XYZ")) {
248
146
    kind = destXYZ;
249
146
    if (a->getLength() < 3) {
250
7
      changeLeft = gFalse;
251
139
    } else {
252
139
      a->get(2, &obj2);
253
139
      if (obj2.isNull()) {
254
23
  changeLeft = gFalse;
255
116
      } else if (obj2.isNum()) {
256
108
  changeLeft = gTrue;
257
108
  left = obj2.getNum();
258
108
      } else {
259
8
  error(errSyntaxWarning, -1, "Bad annotation destination position");
260
8
  goto err1;
261
8
      }
262
131
      obj2.free();
263
131
    }
264
138
    if (a->getLength() < 4) {
265
7
      changeTop = gFalse;
266
131
    } else {
267
131
      a->get(3, &obj2);
268
131
      if (obj2.isNull()) {
269
1
  changeTop = gFalse;
270
130
      } else if (obj2.isNum()) {
271
97
  changeTop = gTrue;
272
97
  top = obj2.getNum();
273
97
      } else {
274
33
  error(errSyntaxWarning, -1, "Bad annotation destination position");
275
33
  goto err1;
276
33
      }
277
98
      obj2.free();
278
98
    }
279
105
    if (a->getLength() < 5) {
280
9
      changeZoom = gFalse;
281
96
    } else {
282
96
      a->get(4, &obj2);
283
96
      if (obj2.isNull()) {
284
54
  changeZoom = gFalse;
285
54
      } else if (obj2.isNum()) {
286
30
  changeZoom = gTrue;
287
30
  zoom = obj2.getNum();
288
30
      } else {
289
12
  error(errSyntaxWarning, -1, "Bad annotation destination position");
290
12
  goto err1;
291
12
      }
292
84
      obj2.free();
293
84
    }
294
295
  // Fit link
296
152
  } else if (obj1.isName("Fit")) {
297
2
    if (a->getLength() < 2) {
298
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
299
0
      goto err2;
300
0
    }
301
2
    kind = destFit;
302
303
  // FitH link
304
150
  } else if (obj1.isName("FitH")) {
305
98
    if (a->getLength() < 3) {
306
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
307
0
      goto err2;
308
0
    }
309
98
    kind = destFitH;
310
98
    if (a->get(2, &obj2)->isNum()) {
311
94
      top = obj2.getNum();
312
94
      changeTop = gTrue;
313
94
    } else if (obj2.isNull()) {
314
1
      changeTop = gFalse;
315
3
    } else {
316
3
      error(errSyntaxWarning, -1, "Bad annotation destination position");
317
3
      kind = destFit;
318
3
    }
319
98
    obj2.free();
320
321
  // FitV link
322
98
  } else if (obj1.isName("FitV")) {
323
26
    if (a->getLength() < 3) {
324
6
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
325
6
      goto err2;
326
6
    }
327
20
    kind = destFitV;
328
20
    if (a->get(2, &obj2)->isNum()) {
329
8
      left = obj2.getNum();
330
8
      changeLeft = gTrue;
331
12
    } else if (obj2.isNull()) {
332
0
      changeLeft = gFalse;
333
12
    } else {
334
12
      error(errSyntaxWarning, -1, "Bad annotation destination position");
335
12
      kind = destFit;
336
12
    }
337
20
    obj2.free();
338
339
  // FitR link
340
26
  } else if (obj1.isName("FitR")) {
341
0
    if (a->getLength() < 6) {
342
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
343
0
      goto err2;
344
0
    }
345
0
    kind = destFitR;
346
0
    if (a->get(2, &obj2)->isNum()) {
347
0
      left = obj2.getNum();
348
0
    } else {
349
0
      error(errSyntaxWarning, -1, "Bad annotation destination position");
350
0
      kind = destFit;
351
0
    }
352
0
    obj2.free();
353
0
    if (!a->get(3, &obj2)->isNum()) {
354
0
      error(errSyntaxWarning, -1, "Bad annotation destination position");
355
0
      kind = destFit;
356
0
    }
357
0
    bottom = obj2.getNum();
358
0
    obj2.free();
359
0
    if (!a->get(4, &obj2)->isNum()) {
360
0
      error(errSyntaxWarning, -1, "Bad annotation destination position");
361
0
      kind = destFit;
362
0
    }
363
0
    right = obj2.getNum();
364
0
    obj2.free();
365
0
    if (!a->get(5, &obj2)->isNum()) {
366
0
      error(errSyntaxWarning, -1, "Bad annotation destination position");
367
0
      kind = destFit;
368
0
    }
369
0
    top = obj2.getNum();
370
0
    obj2.free();
371
372
  // FitB link
373
26
  } else if (obj1.isName("FitB")) {
374
0
    if (a->getLength() < 2) {
375
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
376
0
      goto err2;
377
0
    }
378
0
    kind = destFitB;
379
380
  // FitBH link
381
26
  } else if (obj1.isName("FitBH")) {
382
0
    if (a->getLength() < 3) {
383
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
384
0
      goto err2;
385
0
    }
386
0
    kind = destFitBH;
387
0
    if (a->get(2, &obj2)->isNum()) {
388
0
      top = obj2.getNum();
389
0
      changeTop = gTrue;
390
0
    } else if (obj2.isNull()) {
391
0
      changeTop = gFalse;
392
0
    } else {
393
0
      error(errSyntaxWarning, -1, "Bad annotation destination position");
394
0
      kind = destFit;
395
0
    }
396
0
    obj2.free();
397
398
  // FitBV link
399
26
  } else if (obj1.isName("FitBV")) {
400
0
    if (a->getLength() < 3) {
401
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
402
0
      goto err2;
403
0
    }
404
0
    kind = destFitBV;
405
0
    if (a->get(2, &obj2)->isNum()) {
406
0
      left = obj2.getNum();
407
0
      changeLeft = gTrue;
408
0
    } else if (obj2.isNull()) {
409
0
      changeLeft = gFalse;
410
0
    } else {
411
0
      error(errSyntaxWarning, -1, "Bad annotation destination position");
412
0
      kind = destFit;
413
0
    }
414
0
    obj2.free();
415
416
  // unknown link kind
417
26
  } else {
418
26
    error(errSyntaxWarning, -1, "Unknown annotation destination type");
419
26
    goto err2;
420
26
  }
421
422
213
  obj1.free();
423
213
  ok = gTrue;
424
213
  return;
425
426
53
 err1:
427
53
  obj2.free();
428
94
 err2:
429
94
  obj1.free();
430
94
}
431
432
0
LinkDest::LinkDest(LinkDest *dest) {
433
0
  kind = dest->kind;
434
0
  pageIsRef = dest->pageIsRef;
435
0
  if (pageIsRef)
436
0
    pageRef = dest->pageRef;
437
0
  else
438
0
    pageNum = dest->pageNum;
439
0
  left = dest->left;
440
0
  bottom = dest->bottom;
441
0
  right = dest->right;
442
0
  top = dest->top;
443
0
  zoom = dest->zoom;
444
0
  changeLeft = dest->changeLeft;
445
0
  changeTop = dest->changeTop;
446
0
  changeZoom = dest->changeZoom;
447
0
  ok = gTrue;
448
0
}
449
450
//------------------------------------------------------------------------
451
// LinkGoTo
452
//------------------------------------------------------------------------
453
454
403
LinkGoTo::LinkGoTo(Object *destObj) {
455
403
  dest = NULL;
456
403
  namedDest = NULL;
457
458
  // named destination
459
403
  if (destObj->isName()) {
460
4
    namedDest = new GString(destObj->getName());
461
399
  } else if (destObj->isString()) {
462
54
    namedDest = destObj->getString()->copy();
463
464
  // destination dictionary
465
345
  } else if (destObj->isArray()) {
466
315
    dest = new LinkDest(destObj->getArray());
467
315
    if (!dest->isOk()) {
468
102
      delete dest;
469
102
      dest = NULL;
470
102
    }
471
472
  // error
473
315
  } else {
474
30
    error(errSyntaxWarning, -1, "Illegal annotation destination");
475
30
  }
476
403
}
477
478
218
LinkGoTo::~LinkGoTo() {
479
218
  if (dest)
480
86
    delete dest;
481
218
  if (namedDest)
482
0
    delete namedDest;
483
218
}
484
485
//------------------------------------------------------------------------
486
// LinkGoToR
487
//------------------------------------------------------------------------
488
489
268
LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
490
268
  dest = NULL;
491
268
  namedDest = NULL;
492
493
  // get file name
494
268
  fileName = getFileSpecName(fileSpecObj);
495
496
  // named destination
497
268
  if (destObj->isName()) {
498
43
    namedDest = new GString(destObj->getName());
499
225
  } else if (destObj->isString()) {
500
107
    namedDest = destObj->getString()->copy();
501
502
  // destination dictionary
503
118
  } else if (destObj->isArray()) {
504
0
    dest = new LinkDest(destObj->getArray());
505
0
    if (!dest->isOk()) {
506
0
      delete dest;
507
0
      dest = NULL;
508
0
    }
509
510
  // error
511
118
  } else {
512
118
    error(errSyntaxWarning, -1, "Illegal annotation destination");
513
118
  }
514
268
}
515
516
254
LinkGoToR::~LinkGoToR() {
517
254
  if (fileName)
518
4
    delete fileName;
519
254
  if (dest)
520
0
    delete dest;
521
254
  if (namedDest)
522
136
    delete namedDest;
523
254
}
524
525
526
//------------------------------------------------------------------------
527
// LinkLaunch
528
//------------------------------------------------------------------------
529
530
0
LinkLaunch::LinkLaunch(Object *actionObj) {
531
0
  Object obj1, obj2;
532
533
0
  fileName = NULL;
534
0
  params = NULL;
535
536
0
  if (actionObj->isDict()) {
537
0
    if (!actionObj->dictLookup("F", &obj1)->isNull()) {
538
0
      fileName = getFileSpecName(&obj1);
539
0
    } else {
540
0
      obj1.free();
541
#ifdef _WIN32
542
      if (actionObj->dictLookup("Win", &obj1)->isDict()) {
543
  obj1.dictLookup("F", &obj2);
544
  fileName = getFileSpecName(&obj2);
545
  obj2.free();
546
  if (obj1.dictLookup("P", &obj2)->isString()) {
547
    params = obj2.getString()->copy();
548
  }
549
  obj2.free();
550
      } else {
551
  error(errSyntaxWarning, -1, "Bad launch-type link action");
552
      }
553
#else
554
      //~ This hasn't been defined by Adobe yet, so assume it looks
555
      //~ just like the Win dictionary until they say otherwise.
556
0
      if (actionObj->dictLookup("Unix", &obj1)->isDict()) {
557
0
  obj1.dictLookup("F", &obj2);
558
0
  fileName = getFileSpecName(&obj2);
559
0
  obj2.free();
560
0
  if (obj1.dictLookup("P", &obj2)->isString()) {
561
0
    params = obj2.getString()->copy();
562
0
  }
563
0
  obj2.free();
564
0
      } else {
565
0
  error(errSyntaxWarning, -1, "Bad launch-type link action");
566
0
      }
567
0
#endif
568
0
    }
569
0
    obj1.free();
570
0
  }
571
0
}
572
573
0
LinkLaunch::~LinkLaunch() {
574
0
  if (fileName)
575
0
    delete fileName;
576
0
  if (params)
577
0
    delete params;
578
0
}
579
580
//------------------------------------------------------------------------
581
// LinkURI
582
//------------------------------------------------------------------------
583
584
371
LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
585
371
  GString *uri2;
586
371
  int n;
587
371
  char c;
588
589
371
  uri = NULL;
590
371
  if (uriObj->isString()) {
591
298
    uri2 = uriObj->getString();
592
298
    n = (int)strcspn(uri2->getCString(), "/:");
593
298
    if (n < uri2->getLength() && uri2->getChar(n) == ':') {
594
      // "http:..." etc.
595
281
      uri = uri2->copy();
596
281
    } else if (!uri2->cmpN("www.", 4)) {
597
      // "www.[...]" without the leading "http://"
598
6
      uri = new GString("http://");
599
6
      uri->append(uri2);
600
11
    } else {
601
      // relative URI
602
11
      if (baseURI) {
603
11
  uri = baseURI->copy();
604
11
  c = uri->getChar(uri->getLength() - 1);
605
11
  if (c != '/' && c != '?') {
606
0
    uri->append('/');
607
0
  }
608
11
  if (uri2->getChar(0) == '/') {
609
1
    uri->append(uri2->getCString() + 1, uri2->getLength() - 1);
610
10
  } else {
611
10
    uri->append(uri2);
612
10
  }
613
11
      } else {
614
0
  uri = uri2->copy();
615
0
      }
616
11
    }
617
298
  } else {
618
73
    error(errSyntaxWarning, -1, "Illegal URI-type link");
619
73
  }
620
371
}
621
622
73
LinkURI::~LinkURI() {
623
73
  if (uri)
624
0
    delete uri;
625
73
}
626
627
//------------------------------------------------------------------------
628
// LinkNamed
629
//------------------------------------------------------------------------
630
631
0
LinkNamed::LinkNamed(Object *nameObj) {
632
0
  name = NULL;
633
0
  if (nameObj->isName()) {
634
0
    name = new GString(nameObj->getName());
635
0
  }
636
0
}
637
638
0
LinkNamed::~LinkNamed() {
639
0
  if (name) {
640
0
    delete name;
641
0
  }
642
0
}
643
644
//------------------------------------------------------------------------
645
// LinkMovie
646
//------------------------------------------------------------------------
647
648
0
LinkMovie::LinkMovie(Object *annotObj, Object *titleObj) {
649
0
  annotRef.num = -1;
650
0
  title = NULL;
651
0
  if (annotObj->isRef()) {
652
0
    annotRef = annotObj->getRef();
653
0
  } else if (titleObj->isString()) {
654
0
    title = titleObj->getString()->copy();
655
0
  } else {
656
0
    error(errSyntaxError, -1,
657
0
    "Movie action is missing both the Annot and T keys");
658
0
  }
659
0
}
660
661
0
LinkMovie::~LinkMovie() {
662
0
  if (title) {
663
0
    delete title;
664
0
  }
665
0
}
666
667
//------------------------------------------------------------------------
668
// LinkJavaScript
669
//------------------------------------------------------------------------
670
671
36
LinkJavaScript::LinkJavaScript(Object *jsObj) {
672
36
  char buf[4096];
673
36
  int n;
674
675
36
  if (jsObj->isString()) {
676
7
    js = jsObj->getString()->copy();
677
29
  } else if (jsObj->isStream()) {
678
4
    js = new GString();
679
4
    jsObj->streamReset();
680
6
    while ((n = jsObj->getStream()->getBlock(buf, sizeof(buf))) > 0) {
681
2
      js->append(buf, n);
682
2
    }
683
4
    jsObj->streamClose();
684
25
  } else {
685
25
    error(errSyntaxError, -1, "JavaScript action JS key is wrong type");
686
25
    js = NULL;
687
25
  }
688
36
}
689
690
25
LinkJavaScript::~LinkJavaScript() {
691
25
  if (js) {
692
0
    delete js;
693
0
  }
694
25
}
695
696
//------------------------------------------------------------------------
697
// LinkSubmitForm
698
//------------------------------------------------------------------------
699
700
LinkSubmitForm::LinkSubmitForm(Object *urlObj, Object *fieldsObj,
701
0
             Object *flagsObj) {
702
0
  if (urlObj->isString()) {
703
0
    url = urlObj->getString()->copy();
704
0
  } else {
705
0
    error(errSyntaxError, -1, "SubmitForm action URL is wrong type");
706
0
    url = NULL;
707
0
  }
708
709
0
  if (fieldsObj->isArray()) {
710
0
    fieldsObj->copy(&fields);
711
0
  } else {
712
0
    if (!fieldsObj->isNull()) {
713
0
      error(errSyntaxError, -1, "SubmitForm action Fields value is wrong type");
714
0
    }
715
0
    fields.initNull();
716
0
  }
717
718
0
  if (flagsObj->isInt()) {
719
0
    flags = flagsObj->getInt();
720
0
  } else {
721
0
    if (!flagsObj->isNull()) {
722
0
      error(errSyntaxError, -1, "SubmitForm action Flags value is wrong type");
723
0
    }
724
0
    flags = 0;
725
0
  }
726
0
}
727
728
0
LinkSubmitForm::~LinkSubmitForm() {
729
0
  if (url) {
730
0
    delete url;
731
0
  }
732
0
  fields.free();
733
0
}
734
735
//------------------------------------------------------------------------
736
// LinkHide
737
//------------------------------------------------------------------------
738
739
0
LinkHide::LinkHide(Object *fieldsObj, Object *hideFlagObj) {
740
0
  if (fieldsObj->isRef() || fieldsObj->isString() || fieldsObj->isArray()) {
741
0
    fieldsObj->copy(&fields);
742
0
  } else {
743
0
    error(errSyntaxError, -1, "Hide action T value is wrong type");
744
0
    fields.initNull();
745
0
  }
746
747
0
  if (hideFlagObj->isBool()) {
748
0
    hideFlag = hideFlagObj->getBool();
749
0
  } else {
750
0
    error(errSyntaxError, -1, "Hide action H value is wrong type");
751
0
    hideFlag = gFalse;
752
0
  }
753
0
}
754
755
0
LinkHide::~LinkHide() {
756
0
  fields.free();
757
0
}
758
759
//------------------------------------------------------------------------
760
// LinkUnknown
761
//------------------------------------------------------------------------
762
763
120
LinkUnknown::LinkUnknown(char *actionA) {
764
120
  action = new GString(actionA);
765
120
}
766
767
13
LinkUnknown::~LinkUnknown() {
768
13
  delete action;
769
13
}
770
771
//------------------------------------------------------------------------
772
// Link
773
//------------------------------------------------------------------------
774
775
4.21k
Link::Link(Dict *dict, GString *baseURI) {
776
4.21k
  Object obj1, obj2;
777
4.21k
  double t;
778
779
4.21k
  action = NULL;
780
4.21k
  ok = gFalse;
781
782
  // get rectangle
783
4.21k
  if (!dict->lookup("Rect", &obj1)->isArray()) {
784
561
    error(errSyntaxError, -1, "Annotation rectangle is wrong type");
785
561
    goto err2;
786
561
  }
787
3.65k
  if (!obj1.arrayGet(0, &obj2)->isNum()) {
788
239
    error(errSyntaxError, -1, "Bad annotation rectangle");
789
239
    goto err1;
790
239
  }
791
3.41k
  x1 = obj2.getNum();
792
3.41k
  obj2.free();
793
3.41k
  if (!obj1.arrayGet(1, &obj2)->isNum()) {
794
114
    error(errSyntaxError, -1, "Bad annotation rectangle");
795
114
    goto err1;
796
114
  }
797
3.30k
  y1 = obj2.getNum();
798
3.30k
  obj2.free();
799
3.30k
  if (!obj1.arrayGet(2, &obj2)->isNum()) {
800
227
    error(errSyntaxError, -1, "Bad annotation rectangle");
801
227
    goto err1;
802
227
  }
803
3.07k
  x2 = obj2.getNum();
804
3.07k
  obj2.free();
805
3.07k
  if (!obj1.arrayGet(3, &obj2)->isNum()) {
806
585
    error(errSyntaxError, -1, "Bad annotation rectangle");
807
585
    goto err1;
808
585
  }
809
2.49k
  y2 = obj2.getNum();
810
2.49k
  obj2.free();
811
2.49k
  obj1.free();
812
2.49k
  if (x1 > x2) {
813
174
    t = x1;
814
174
    x1 = x2;
815
174
    x2 = t;
816
174
  }
817
2.49k
  if (y1 > y2) {
818
201
    t = y1;
819
201
    y1 = y2;
820
201
    y2 = t;
821
201
  }
822
823
  // look for destination
824
2.49k
  if (!dict->lookup("Dest", &obj1)->isNull()) {
825
76
    action = LinkAction::parseDest(&obj1);
826
827
  // look for action
828
2.41k
  } else {
829
2.41k
    obj1.free();
830
2.41k
    if (dict->lookup("A", &obj1)->isDict()) {
831
1.23k
      action = LinkAction::parseAction(&obj1, baseURI);
832
1.23k
    }
833
2.41k
  }
834
2.49k
  obj1.free();
835
836
  // check for bad action
837
2.49k
  if (action) {
838
615
    ok = gTrue;
839
615
  }
840
841
2.49k
  return;
842
843
1.16k
 err1:
844
1.16k
  obj2.free();
845
1.72k
 err2:
846
1.72k
  obj1.free();
847
1.72k
}
848
849
3.60k
Link::~Link() {
850
3.60k
  if (action) {
851
0
    delete action;
852
0
  }
853
3.60k
}
854
855
//------------------------------------------------------------------------
856
// Links
857
//------------------------------------------------------------------------
858
859
306k
Links::Links(Object *annots, GString *baseURI) {
860
306k
  Link *link;
861
306k
  Object obj1, obj2, obj3;
862
306k
  int size;
863
306k
  int i;
864
865
306k
  links = NULL;
866
306k
  size = 0;
867
306k
  numLinks = 0;
868
869
306k
  if (annots->isArray()) {
870
517k
    for (i = 0; i < annots->arrayGetLength(); ++i) {
871
507k
      if (annots->arrayGet(i, &obj1)->isDict()) {
872
36.9k
  obj1.dictLookup("Subtype", &obj2);
873
36.9k
  obj1.dictLookup("FT", &obj3);
874
36.9k
  if (obj2.isName("Link") ||
875
34.9k
      (obj2.isName("Widget") && (obj3.isName("Btn") || obj3.isNull()))) {
876
4.21k
    link = new Link(obj1.getDict(), baseURI);
877
4.21k
    if (link->isOk()) {
878
615
      if (numLinks >= size) {
879
196
        size += 16;
880
196
        links = (Link **)greallocn(links, size, sizeof(Link *));
881
196
      }
882
615
      links[numLinks++] = link;
883
3.60k
    } else {
884
3.60k
      delete link;
885
3.60k
    }
886
4.21k
  }
887
36.9k
  obj3.free();
888
36.9k
  obj2.free();
889
36.9k
      }
890
507k
      obj1.free();
891
507k
    }
892
9.48k
  }
893
306k
}
894
895
0
Links::~Links() {
896
0
  int i;
897
898
0
  for (i = 0; i < numLinks; ++i)
899
0
    delete links[i];
900
0
  gfree(links);
901
0
}
902
903
0
LinkAction *Links::find(double x, double y) {
904
0
  int i;
905
906
0
  for (i = numLinks - 1; i >= 0; --i) {
907
0
    if (links[i]->inRect(x, y)) {
908
0
      return links[i]->getAction();
909
0
    }
910
0
  }
911
0
  return NULL;
912
0
}
913
914
0
GBool Links::onLink(double x, double y) {
915
0
  int i;
916
917
0
  for (i = 0; i < numLinks; ++i) {
918
0
    if (links[i]->inRect(x, y))
919
0
      return gTrue;
920
0
  }
921
0
  return gFalse;
922
0
}