Coverage Report

Created: 2026-03-15 06:39

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