Merge pull request #8825 from Snuffleupagus/simpleDest-dictionary
Account for broken outlines/annotations, where the destination dictionary contains an invalid `/Dest` entry
This commit is contained in:
		
						commit
						a0eed974a3
					
				@ -640,20 +640,32 @@ var Catalog = (function CatalogClosure() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var destDict = params.destDict;
 | 
					    var destDict = params.destDict;
 | 
				
			||||||
    if (!isDict(destDict)) {
 | 
					    if (!isDict(destDict)) {
 | 
				
			||||||
      warn('Catalog_parseDestDictionary: "destDict" must be a dictionary.');
 | 
					      warn('parseDestDictionary: "destDict" must be a dictionary.');
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    var resultObj = params.resultObj;
 | 
					    var resultObj = params.resultObj;
 | 
				
			||||||
    if (typeof resultObj !== 'object') {
 | 
					    if (typeof resultObj !== 'object') {
 | 
				
			||||||
      warn('Catalog_parseDestDictionary: "resultObj" must be an object.');
 | 
					      warn('parseDestDictionary: "resultObj" must be an object.');
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    var docBaseUrl = params.docBaseUrl || null;
 | 
					    var docBaseUrl = params.docBaseUrl || null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var action = destDict.get('A'), url, dest;
 | 
					    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)) {
 | 
					    if (isDict(action)) {
 | 
				
			||||||
      var linkType = action.get('S').name;
 | 
					      let actionType = action.get('S');
 | 
				
			||||||
      switch (linkType) {
 | 
					      if (!isName(actionType)) {
 | 
				
			||||||
 | 
					        warn('parseDestDictionary: Invalid type in Action dictionary.');
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      let actionName = actionType.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      switch (actionName) {
 | 
				
			||||||
        case 'URI':
 | 
					        case 'URI':
 | 
				
			||||||
          url = action.get('URI');
 | 
					          url = action.get('URI');
 | 
				
			||||||
          if (isName(url)) {
 | 
					          if (isName(url)) {
 | 
				
			||||||
@ -748,11 +760,10 @@ var Catalog = (function CatalogClosure() {
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
          /* falls through */
 | 
					          /* falls through */
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
          warn('Catalog_parseDestDictionary: Unrecognized link type "' +
 | 
					          warn(`parseDestDictionary: Unsupported Action type "${actionName}".`);
 | 
				
			||||||
               linkType + '".');
 | 
					 | 
				
			||||||
          break;
 | 
					          break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else if (destDict.has('Dest')) { // Simple destination link.
 | 
					    } else if (destDict.has('Dest')) { // Simple destination.
 | 
				
			||||||
      dest = destDict.get('Dest');
 | 
					      dest = destDict.get('Dest');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -689,6 +689,36 @@ describe('annotation', function() {
 | 
				
			|||||||
      expect(data.dest).toEqual([{ num: 17, gen: 0, }, { name: 'XYZ', },
 | 
					      expect(data.dest).toEqual([{ num: 17, gen: 0, }, { name: 'XYZ', },
 | 
				
			||||||
                                 0, 841.89, null]);
 | 
					                                 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() {
 | 
					  describe('WidgetAnnotation', function() {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user