Coverage Report

Created: 2026-04-09 06:17

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
583
LinkAction *LinkAction::parseDest(Object *obj) {
27
583
  LinkAction *action;
28
29
583
  action = new LinkGoTo(obj);
30
583
  if (!action->isOk()) {
31
235
    delete action;
32
235
    return NULL;
33
235
  }
34
348
  return action;
35
583
}
36
37
1.72k
LinkAction *LinkAction::parseAction(Object *obj, GString *baseURI) {
38
1.72k
  LinkAction *action;
39
1.72k
  Object obj2, obj3, obj4, obj5;
40
41
1.72k
  if (!obj->isDict()) {
42
88
    error(errSyntaxWarning, -1, "Bad annotation action");
43
88
    return NULL;
44
88
  }
45
46
1.63k
  obj->dictLookup("S", &obj2);
47
48
  // GoTo action
49
1.63k
  if (obj2.isName("GoTo")) {
50
364
    obj->dictLookup("D", &obj3);
51
364
    action = new LinkGoTo(&obj3);
52
364
    obj3.free();
53
54
  // GoToR action
55
1.27k
  } else if (obj2.isName("GoToR")) {
56
288
    obj->dictLookup("F", &obj3);
57
288
    obj->dictLookup("D", &obj4);
58
288
    action = new LinkGoToR(&obj3, &obj4);
59
288
    obj3.free();
60
288
    obj4.free();
61
62
  // Launch action
63
985
  } else if (obj2.isName("Launch")) {
64
0
    action = new LinkLaunch(obj);
65
66
  // URI action
67
985
  } else if (obj2.isName("URI")) {
68
592
    obj->dictLookup("URI", &obj3);
69
592
    action = new LinkURI(&obj3, baseURI);
70
592
    obj3.free();
71
72
  // Named action
73
592
  } 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
393
  } 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
393
  } else if (obj2.isName("JavaScript")) {
88
61
    obj->dictLookup("JS", &obj3);
89
61
    action = new LinkJavaScript(&obj3);
90
61
    obj3.free();
91
92
  // SubmitForm action
93
332
  } 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
332
  } 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
332
  } else if (obj2.isName()) {
112
104
    action = new LinkUnknown(obj2.getName());
113
114
  // action is missing or wrong type
115
228
  } else {
116
228
    error(errSyntaxWarning, -1, "Bad annotation action");
117
228
    action = NULL;
118
228
  }
119
120
1.63k
  obj2.free();
121
122
1.63k
  if (action && !action->isOk()) {
123
490
    delete action;
124
490
    return NULL;
125
490
  }
126
1.14k
  return action;
127
1.63k
}
128
129
288
GString *LinkAction::getFileSpecName(Object *fileSpecObj) {
130
288
  GString *name;
131
288
  Object obj1;
132
133
288
  name = NULL;
134
135
  // string
136
288
  if (fileSpecObj->isString()) {
137
23
    name = fileSpecObj->getString()->copy();
138
139
  // dictionary
140
265
  } else if (fileSpecObj->isDict()) {
141
#ifdef _WIN32
142
    if (!fileSpecObj->dictLookup("DOS", &obj1)->isString()) {
143
#else
144
15
    if (!fileSpecObj->dictLookup("Unix", &obj1)->isString()) {
145
15
#endif
146
15
      obj1.free();
147
15
      fileSpecObj->dictLookup("F", &obj1);
148
15
    }
149
15
    if (obj1.isString()) {
150
9
      name = obj1.getString()->copy();
151
9
    } else {
152
6
      error(errSyntaxWarning, -1, "Illegal file spec in link");
153
6
    }
154
15
    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
288
  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
32
#endif
208
32
  }
209
210
288
  return name;
211
288
}
212
213
//------------------------------------------------------------------------
214
// LinkDest
215
//------------------------------------------------------------------------
216
217
845
LinkDest::LinkDest(Array *a) {
218
845
  Object obj1, obj2;
219
220
  // initialize fields
221
845
  left = bottom = right = top = zoom = 0;
222
845
  ok = gFalse;
223
224
  // get page
225
845
  if (a->getLength() < 2) {
226
22
    error(errSyntaxWarning, -1, "Annotation destination array is too short");
227
22
    return;
228
22
  }
229
823
  a->getNF(0, &obj1);
230
823
  if (obj1.isInt()) {
231
32
    pageNum = obj1.getInt() + 1;
232
32
    pageIsRef = gFalse;
233
791
  } else if (obj1.isRef()) {
234
763
    pageRef.num = obj1.getRefNum();
235
763
    pageRef.gen = obj1.getRefGen();
236
763
    pageIsRef = gTrue;
237
763
  } else {
238
28
    error(errSyntaxWarning, -1, "Bad annotation destination");
239
28
    goto err2;
240
28
  }
241
795
  obj1.free();
242
243
  // get destination type
244
795
  a->get(1, &obj1);
245
246
  // XYZ link
247
795
  if (obj1.isName("XYZ")) {
248
330
    kind = destXYZ;
249
330
    if (a->getLength() < 3) {
250
18
      changeLeft = gFalse;
251
312
    } else {
252
312
      a->get(2, &obj2);
253
312
      if (obj2.isNull()) {
254
73
  changeLeft = gFalse;
255
239
      } else if (obj2.isNum()) {
256
223
  changeLeft = gTrue;
257
223
  left = obj2.getNum();
258
223
      } else {
259
16
  error(errSyntaxWarning, -1, "Bad annotation destination position");
260
16
  goto err1;
261
16
      }
262
296
      obj2.free();
263
296
    }
264
314
    if (a->getLength() < 4) {
265
30
      changeTop = gFalse;
266
284
    } else {
267
284
      a->get(3, &obj2);
268
284
      if (obj2.isNull()) {
269
17
  changeTop = gFalse;
270
267
      } else if (obj2.isNum()) {
271
186
  changeTop = gTrue;
272
186
  top = obj2.getNum();
273
186
      } else {
274
81
  error(errSyntaxWarning, -1, "Bad annotation destination position");
275
81
  goto err1;
276
81
      }
277
203
      obj2.free();
278
203
    }
279
233
    if (a->getLength() < 5) {
280
37
      changeZoom = gFalse;
281
196
    } else {
282
196
      a->get(4, &obj2);
283
196
      if (obj2.isNull()) {
284
76
  changeZoom = gFalse;
285
120
      } else if (obj2.isNum()) {
286
81
  changeZoom = gTrue;
287
81
  zoom = obj2.getNum();
288
81
      } else {
289
39
  error(errSyntaxWarning, -1, "Bad annotation destination position");
290
39
  goto err1;
291
39
      }
292
157
      obj2.free();
293
157
    }
294
295
  // Fit link
296
465
  } else if (obj1.isName("Fit")) {
297
9
    if (a->getLength() < 2) {
298
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
299
0
      goto err2;
300
0
    }
301
9
    kind = destFit;
302
303
  // FitH link
304
456
  } else if (obj1.isName("FitH")) {
305
162
    if (a->getLength() < 3) {
306
10
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
307
10
      goto err2;
308
10
    }
309
152
    kind = destFitH;
310
152
    if (a->get(2, &obj2)->isNum()) {
311
122
      top = obj2.getNum();
312
122
      changeTop = gTrue;
313
122
    } else if (obj2.isNull()) {
314
7
      changeTop = gFalse;
315
23
    } else {
316
23
      error(errSyntaxWarning, -1, "Bad annotation destination position");
317
23
      kind = destFit;
318
23
    }
319
152
    obj2.free();
320
321
  // FitV link
322
294
  } else if (obj1.isName("FitV")) {
323
93
    if (a->getLength() < 3) {
324
18
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
325
18
      goto err2;
326
18
    }
327
75
    kind = destFitV;
328
75
    if (a->get(2, &obj2)->isNum()) {
329
36
      left = obj2.getNum();
330
36
      changeLeft = gTrue;
331
39
    } else if (obj2.isNull()) {
332
9
      changeLeft = gFalse;
333
30
    } else {
334
30
      error(errSyntaxWarning, -1, "Bad annotation destination position");
335
30
      kind = destFit;
336
30
    }
337
75
    obj2.free();
338
339
  // FitR link
340
201
  } else if (obj1.isName("FitR")) {
341
41
    if (a->getLength() < 6) {
342
10
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
343
10
      goto err2;
344
10
    }
345
31
    kind = destFitR;
346
31
    if (a->get(2, &obj2)->isNum()) {
347
17
      left = obj2.getNum();
348
17
    } else {
349
14
      error(errSyntaxWarning, -1, "Bad annotation destination position");
350
14
      kind = destFit;
351
14
    }
352
31
    obj2.free();
353
31
    if (!a->get(3, &obj2)->isNum()) {
354
17
      error(errSyntaxWarning, -1, "Bad annotation destination position");
355
17
      kind = destFit;
356
17
    }
357
31
    bottom = obj2.getNum();
358
31
    obj2.free();
359
31
    if (!a->get(4, &obj2)->isNum()) {
360
14
      error(errSyntaxWarning, -1, "Bad annotation destination position");
361
14
      kind = destFit;
362
14
    }
363
31
    right = obj2.getNum();
364
31
    obj2.free();
365
31
    if (!a->get(5, &obj2)->isNum()) {
366
17
      error(errSyntaxWarning, -1, "Bad annotation destination position");
367
17
      kind = destFit;
368
17
    }
369
31
    top = obj2.getNum();
370
31
    obj2.free();
371
372
  // FitB link
373
160
  } else if (obj1.isName("FitB")) {
374
6
    if (a->getLength() < 2) {
375
0
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
376
0
      goto err2;
377
0
    }
378
6
    kind = destFitB;
379
380
  // FitBH link
381
154
  } else if (obj1.isName("FitBH")) {
382
46
    if (a->getLength() < 3) {
383
6
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
384
6
      goto err2;
385
6
    }
386
40
    kind = destFitBH;
387
40
    if (a->get(2, &obj2)->isNum()) {
388
20
      top = obj2.getNum();
389
20
      changeTop = gTrue;
390
20
    } else if (obj2.isNull()) {
391
10
      changeTop = gFalse;
392
10
    } else {
393
10
      error(errSyntaxWarning, -1, "Bad annotation destination position");
394
10
      kind = destFit;
395
10
    }
396
40
    obj2.free();
397
398
  // FitBV link
399
108
  } else if (obj1.isName("FitBV")) {
400
46
    if (a->getLength() < 3) {
401
10
      error(errSyntaxWarning, -1, "Annotation destination array is too short");
402
10
      goto err2;
403
10
    }
404
36
    kind = destFitBV;
405
36
    if (a->get(2, &obj2)->isNum()) {
406
16
      left = obj2.getNum();
407
16
      changeLeft = gTrue;
408
20
    } else if (obj2.isNull()) {
409
10
      changeLeft = gFalse;
410
10
    } else {
411
10
      error(errSyntaxWarning, -1, "Bad annotation destination position");
412
10
      kind = destFit;
413
10
    }
414
36
    obj2.free();
415
416
  // unknown link kind
417
62
  } else {
418
62
    error(errSyntaxWarning, -1, "Unknown annotation destination type");
419
62
    goto err2;
420
62
  }
421
422
543
  obj1.free();
423
543
  ok = gTrue;
424
543
  return;
425
426
136
 err1:
427
136
  obj2.free();
428
280
 err2:
429
280
  obj1.free();
430
280
}
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
947
LinkGoTo::LinkGoTo(Object *destObj) {
455
947
  dest = NULL;
456
947
  namedDest = NULL;
457
458
  // named destination
459
947
  if (destObj->isName()) {
460
15
    namedDest = new GString(destObj->getName());
461
932
  } else if (destObj->isString()) {
462
69
    namedDest = destObj->getString()->copy();
463
464
  // destination dictionary
465
863
  } else if (destObj->isArray()) {
466
828
    dest = new LinkDest(destObj->getArray());
467
828
    if (!dest->isOk()) {
468
291
      delete dest;
469
291
      dest = NULL;
470
291
    }
471
472
  // error
473
828
  } else {
474
35
    error(errSyntaxWarning, -1, "Illegal annotation destination");
475
35
  }
476
947
}
477
478
763
LinkGoTo::~LinkGoTo() {
479
763
  if (dest)
480
419
    delete dest;
481
763
  if (namedDest)
482
18
    delete namedDest;
483
763
}
484
485
//------------------------------------------------------------------------
486
// LinkGoToR
487
//------------------------------------------------------------------------
488
489
288
LinkGoToR::LinkGoToR(Object *fileSpecObj, Object *destObj) {
490
288
  dest = NULL;
491
288
  namedDest = NULL;
492
493
  // get file name
494
288
  fileName = getFileSpecName(fileSpecObj);
495
496
  // named destination
497
288
  if (destObj->isName()) {
498
6
    namedDest = new GString(destObj->getName());
499
282
  } else if (destObj->isString()) {
500
67
    namedDest = destObj->getString()->copy();
501
502
  // destination dictionary
503
215
  } else if (destObj->isArray()) {
504
17
    dest = new LinkDest(destObj->getArray());
505
17
    if (!dest->isOk()) {
506
11
      delete dest;
507
11
      dest = NULL;
508
11
    }
509
510
  // error
511
198
  } else {
512
198
    error(errSyntaxWarning, -1, "Illegal annotation destination");
513
198
  }
514
288
}
515
516
277
LinkGoToR::~LinkGoToR() {
517
277
  if (fileName)
518
21
    delete fileName;
519
277
  if (dest)
520
6
    delete dest;
521
277
  if (namedDest)
522
62
    delete namedDest;
523
277
}
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
592
LinkURI::LinkURI(Object *uriObj, GString *baseURI) {
585
592
  GString *uri2;
586
592
  int n;
587
592
  char c;
588
589
592
  uri = NULL;
590
592
  if (uriObj->isString()) {
591
494
    uri2 = uriObj->getString();
592
494
    n = (int)strcspn(uri2->getCString(), "/:");
593
494
    if (n < uri2->getLength() && uri2->getChar(n) == ':') {
594
      // "http:..." etc.
595
438
      uri = uri2->copy();
596
438
    } else if (!uri2->cmpN("www.", 4)) {
597
      // "www.[...]" without the leading "http://"
598
6
      uri = new GString("http://");
599
6
      uri->append(uri2);
600
50
    } else {
601
      // relative URI
602
50
      if (baseURI) {
603
25
  uri = baseURI->copy();
604
25
  c = uri->getChar(uri->getLength() - 1);
605
25
  if (c != '/' && c != '?') {
606
0
    uri->append('/');
607
0
  }
608
25
  if (uri2->getChar(0) == '/') {
609
6
    uri->append(uri2->getCString() + 1, uri2->getLength() - 1);
610
19
  } else {
611
19
    uri->append(uri2);
612
19
  }
613
25
      } else {
614
25
  uri = uri2->copy();
615
25
      }
616
50
    }
617
494
  } else {
618
98
    error(errSyntaxWarning, -1, "Illegal URI-type link");
619
98
  }
620
592
}
621
622
133
LinkURI::~LinkURI() {
623
133
  if (uri)
624
35
    delete uri;
625
133
}
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
61
LinkJavaScript::LinkJavaScript(Object *jsObj) {
672
61
  char buf[4096];
673
61
  int n;
674
675
61
  if (jsObj->isString()) {
676
18
    js = jsObj->getString()->copy();
677
43
  } else if (jsObj->isStream()) {
678
11
    js = new GString();
679
11
    jsObj->streamReset();
680
18
    while ((n = jsObj->getStream()->getBlock(buf, sizeof(buf))) > 0) {
681
7
      js->append(buf, n);
682
7
    }
683
11
    jsObj->streamClose();
684
32
  } else {
685
32
    error(errSyntaxError, -1, "JavaScript action JS key is wrong type");
686
32
    js = NULL;
687
32
  }
688
61
}
689
690
38
LinkJavaScript::~LinkJavaScript() {
691
38
  if (js) {
692
6
    delete js;
693
6
  }
694
38
}
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
104
LinkUnknown::LinkUnknown(char *actionA) {
764
104
  action = new GString(actionA);
765
104
}
766
767
53
LinkUnknown::~LinkUnknown() {
768
53
  delete action;
769
53
}
770
771
//------------------------------------------------------------------------
772
// Link
773
//------------------------------------------------------------------------
774
775
4.80k
Link::Link(Dict *dict, GString *baseURI) {
776
4.80k
  Object obj1, obj2;
777
4.80k
  double t;
778
779
4.80k
  action = NULL;
780
4.80k
  ok = gFalse;
781
782
  // get rectangle
783
4.80k
  if (!dict->lookup("Rect", &obj1)->isArray()) {
784
562
    error(errSyntaxError, -1, "Annotation rectangle is wrong type");
785
562
    goto err2;
786
562
  }
787
4.24k
  if (!obj1.arrayGet(0, &obj2)->isNum()) {
788
256
    error(errSyntaxError, -1, "Bad annotation rectangle");
789
256
    goto err1;
790
256
  }
791
3.98k
  x1 = obj2.getNum();
792
3.98k
  obj2.free();
793
3.98k
  if (!obj1.arrayGet(1, &obj2)->isNum()) {
794
257
    error(errSyntaxError, -1, "Bad annotation rectangle");
795
257
    goto err1;
796
257
  }
797
3.73k
  y1 = obj2.getNum();
798
3.73k
  obj2.free();
799
3.73k
  if (!obj1.arrayGet(2, &obj2)->isNum()) {
800
307
    error(errSyntaxError, -1, "Bad annotation rectangle");
801
307
    goto err1;
802
307
  }
803
3.42k
  x2 = obj2.getNum();
804
3.42k
  obj2.free();
805
3.42k
  if (!obj1.arrayGet(3, &obj2)->isNum()) {
806
647
    error(errSyntaxError, -1, "Bad annotation rectangle");
807
647
    goto err1;
808
647
  }
809
2.77k
  y2 = obj2.getNum();
810
2.77k
  obj2.free();
811
2.77k
  obj1.free();
812
2.77k
  if (x1 > x2) {
813
186
    t = x1;
814
186
    x1 = x2;
815
186
    x2 = t;
816
186
  }
817
2.77k
  if (y1 > y2) {
818
313
    t = y1;
819
313
    y1 = y2;
820
313
    y2 = t;
821
313
  }
822
823
  // look for destination
824
2.77k
  if (!dict->lookup("Dest", &obj1)->isNull()) {
825
107
    action = LinkAction::parseDest(&obj1);
826
827
  // look for action
828
2.67k
  } else {
829
2.67k
    obj1.free();
830
2.67k
    if (dict->lookup("A", &obj1)->isDict()) {
831
1.14k
      action = LinkAction::parseAction(&obj1, baseURI);
832
1.14k
    }
833
2.67k
  }
834
2.77k
  obj1.free();
835
836
  // check for bad action
837
2.77k
  if (action) {
838
728
    ok = gTrue;
839
728
  }
840
841
2.77k
  return;
842
843
1.46k
 err1:
844
1.46k
  obj2.free();
845
2.02k
 err2:
846
2.02k
  obj1.free();
847
2.02k
}
848
849
4.07k
Link::~Link() {
850
4.07k
  if (action) {
851
0
    delete action;
852
0
  }
853
4.07k
}
854
855
//------------------------------------------------------------------------
856
// Links
857
//------------------------------------------------------------------------
858
859
401k
Links::Links(Object *annots, GString *baseURI) {
860
401k
  Link *link;
861
401k
  Object obj1, obj2, obj3;
862
401k
  int size;
863
401k
  int i;
864
865
401k
  links = NULL;
866
401k
  size = 0;
867
401k
  numLinks = 0;
868
869
401k
  if (annots->isArray()) {
870
466k
    for (i = 0; i < annots->arrayGetLength(); ++i) {
871
456k
      if (annots->arrayGet(i, &obj1)->isDict()) {
872
35.6k
  obj1.dictLookup("Subtype", &obj2);
873
35.6k
  obj1.dictLookup("FT", &obj3);
874
35.6k
  if (obj2.isName("Link") ||
875
33.5k
      (obj2.isName("Widget") && (obj3.isName("Btn") || obj3.isNull()))) {
876
4.80k
    link = new Link(obj1.getDict(), baseURI);
877
4.80k
    if (link->isOk()) {
878
728
      if (numLinks >= size) {
879
281
        size += 16;
880
281
        links = (Link **)greallocn(links, size, sizeof(Link *));
881
281
      }
882
728
      links[numLinks++] = link;
883
4.07k
    } else {
884
4.07k
      delete link;
885
4.07k
    }
886
4.80k
  }
887
35.6k
  obj3.free();
888
35.6k
  obj2.free();
889
35.6k
      }
890
456k
      obj1.free();
891
456k
    }
892
9.82k
  }
893
401k
}
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
}