Coverage Report

Created: 2023-09-25 06:35

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