diff --git a/src/core/chunked_stream.js b/src/core/chunked_stream.js index 26a93f673..39c1cb677 100644 --- a/src/core/chunked_stream.js +++ b/src/core/chunked_stream.js @@ -218,6 +218,12 @@ class ChunkedStream { } getByteRange(begin, end) { + if (begin < 0) { + begin = 0; + } + if (end > this.end) { + end = this.end; + } this.ensureRange(begin, end); return this.bytes.subarray(begin, end); } diff --git a/src/core/document.js b/src/core/document.js index 05cc27374..73b14e9a9 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -598,20 +598,16 @@ class PDFDocument { idArray[0] !== EMPTY_FINGERPRINT) { hash = stringToBytes(idArray[0]); } else { - if (this.stream.ensureRange) { - this.stream.ensureRange(0, - Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end)); - } - hash = calculateMD5(this.stream.bytes.subarray(0, - FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); + hash = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), + 0, FINGERPRINT_FIRST_BYTES); } - let fingerprint = ''; + const fingerprintBuf = []; for (let i = 0, ii = hash.length; i < ii; i++) { const hex = hash[i].toString(16); - fingerprint += (hex.length === 1 ? '0' + hex : hex); + fingerprintBuf.push(hex.padStart(2, '0')); } - return shadow(this, 'fingerprint', fingerprint); + return shadow(this, 'fingerprint', fingerprintBuf.join('')); } _getLinearizationPage(pageIndex) { diff --git a/src/core/stream.js b/src/core/stream.js index ae57f9023..1867c8c99 100644 --- a/src/core/stream.js +++ b/src/core/stream.js @@ -19,7 +19,9 @@ * license. */ -import { FormatError, isSpace, stringToBytes } from '../shared/util'; +import { + FormatError, isSpace, stringToBytes, unreachable +} from '../shared/util'; import { isDict } from './primitives'; var Stream = (function StreamClosure() { @@ -92,6 +94,17 @@ var Stream = (function StreamClosure() { this.pos -= bytes.length; return bytes; }, + + getByteRange(begin, end) { + if (begin < 0) { + begin = 0; + } + if (end > this.end) { + end = this.end; + } + return this.bytes.subarray(begin, end); + }, + skip: function Stream_skip(n) { if (!n) { n = 1; @@ -236,6 +249,11 @@ var DecodeStream = (function DecodeStreamClosure() { } return new Stream(this.buffer, start, length, dict); }, + + getByteRange(begin, end) { + unreachable('Should not call DecodeStream.getByteRange'); + }, + skip: function DecodeStream_skip(n) { if (!n) { n = 1; diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index 10325b9f3..b32014e08 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -413,9 +413,7 @@ describe('api', function() { expect(doc.numPages).toEqual(3); }); it('gets fingerprint', function() { - var fingerprint = doc.fingerprint; - expect(typeof fingerprint).toEqual('string'); - expect(fingerprint.length > 0).toEqual(true); + expect(doc.fingerprint).toEqual('ea8b35919d6279a369e835bde778611b'); }); it('gets page', function(done) { var promise = doc.getPage(1); @@ -934,23 +932,22 @@ describe('api', function() { }); it('checks that fingerprints are unique', function(done) { - var loadingTask1 = getDocument(buildGetDocumentParams('issue4436r.pdf')); + const loadingTask1 = getDocument( + buildGetDocumentParams('issue4436r.pdf')); + const loadingTask2 = getDocument(buildGetDocumentParams('issue4575.pdf')); - var loadingTask2 = getDocument(buildGetDocumentParams('issue4575.pdf')); - - var promises = [loadingTask1.promise, - loadingTask2.promise]; - Promise.all(promises).then(function (data) { - var fingerprint1 = data[0].fingerprint; - expect(typeof fingerprint1).toEqual('string'); - expect(fingerprint1.length > 0).toEqual(true); - - var fingerprint2 = data[1].fingerprint; - expect(typeof fingerprint2).toEqual('string'); - expect(fingerprint2.length > 0).toEqual(true); + Promise.all([ + loadingTask1.promise, + loadingTask2.promise + ]).then(function(data) { + const fingerprint1 = data[0].fingerprint; + const fingerprint2 = data[1].fingerprint; expect(fingerprint1).not.toEqual(fingerprint2); + expect(fingerprint1).toEqual('2f695a83d6e7553c24fc08b7ac69712d'); + expect(fingerprint2).toEqual('04c7126b34a46b6d4d6e7a1eff7edcb6'); + Promise.all([ loadingTask1.destroy(), loadingTask2.destroy()