Skip to content

Commit

Permalink
Merge pull request mozilla#8825 from Snuffleupagus/simpleDest-dictionary
Browse files Browse the repository at this point in the history
Account for broken outlines/annotations, where the destination dictionary contains an invalid `/Dest` entry
  • Loading branch information
Rob--W authored Aug 26, 2017
2 parents 755a219 + 39b1f23 commit 7db996a
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 7 deletions.
25 changes: 18 additions & 7 deletions src/core/obj.js
Original file line number Diff line number Diff line change
Expand Up @@ -640,20 +640,32 @@ var Catalog = (function CatalogClosure() {

var destDict = params.destDict;
if (!isDict(destDict)) {
warn('Catalog_parseDestDictionary: "destDict" must be a dictionary.');
warn('parseDestDictionary: "destDict" must be a dictionary.');
return;
}
var resultObj = params.resultObj;
if (typeof resultObj !== 'object') {
warn('Catalog_parseDestDictionary: "resultObj" must be an object.');
warn('parseDestDictionary: "resultObj" must be an object.');
return;
}
var docBaseUrl = params.docBaseUrl || null;

var action = destDict.get('A'), url, dest;
if (!isDict(action) && destDict.has('Dest')) {
// A /Dest entry should *only* contain a Name or an Array, but some bad
// PDF generators ignore that and treat it as an /A entry.
action = destDict.get('Dest');
}

if (isDict(action)) {
var linkType = action.get('S').name;
switch (linkType) {
let actionType = action.get('S');
if (!isName(actionType)) {
warn('parseDestDictionary: Invalid type in Action dictionary.');
return;
}
let actionName = actionType.name;

switch (actionName) {
case 'URI':
url = action.get('URI');
if (isName(url)) {
Expand Down Expand Up @@ -748,11 +760,10 @@ var Catalog = (function CatalogClosure() {
}
/* falls through */
default:
warn('Catalog_parseDestDictionary: Unrecognized link type "' +
linkType + '".');
warn(`parseDestDictionary: Unsupported Action type "${actionName}".`);
break;
}
} else if (destDict.has('Dest')) { // Simple destination link.
} else if (destDict.has('Dest')) { // Simple destination.
dest = destDict.get('Dest');
}

Expand Down
30 changes: 30 additions & 0 deletions test/unit/annotation_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,36 @@ describe('annotation', function() {
expect(data.dest).toEqual([{ num: 17, gen: 0, }, { name: 'XYZ', },
0, 841.89, null]);
});

it('should correctly parse a Dest, which violates the specification ' +
'by containing a dictionary', function() {
let destDict = new Dict();
destDict.set('Type', Name.get('Action'));
destDict.set('S', Name.get('GoTo'));
destDict.set('D', 'page.157');

let annotationDict = new Dict();
annotationDict.set('Type', Name.get('Annot'));
annotationDict.set('Subtype', Name.get('Link'));
// The /Dest must be a Name or an Array, refer to ISO 32000-1:2008
// section 12.3.3, but there are PDF files where it's a dictionary.
annotationDict.set('Dest', destDict);

let annotationRef = new Ref(798, 0);
let xref = new XRefMock([
{ ref: annotationRef, data: annotationDict, }
]);

let annotation = annotationFactory.create(xref, annotationRef,
pdfManagerMock, idFactoryMock);
let data = annotation.data;
expect(data.annotationType).toEqual(AnnotationType.LINK);

expect(data.url).toBeUndefined();
expect(data.unsafeUrl).toBeUndefined();
expect(data.dest).toEqual('page.157');
});

});

describe('WidgetAnnotation', function() {
Expand Down

0 comments on commit 7db996a

Please sign in to comment.