Coverage Report

Created: 2026-02-04 06:14

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