Simplify the PDFDocument.fingerprint method slightly

The way that this method handles documents without an `ID` entry in the Trailer dictionary feels overly complicated to me. Hence this patch adds `getByteRange` methods to the various Stream implementations[1], and utilize that rather than manually calling `ensureRange` when computing a fallback `fingerprint`.

---
[1] Note that `PDFDocument` is only ever initialized with either a `Stream` or a `ChunkedStream`, hence why the `DecodeStream.getByteRange` method isn't implemented.
This commit is contained in:
Jonas Jenwald 2019-07-15 11:26:07 +02:00
parent c7de6dbe41
commit bea15b6ce5
3 changed files with 30 additions and 10 deletions

View File

@ -218,6 +218,12 @@ class ChunkedStream {
} }
getByteRange(begin, end) { getByteRange(begin, end) {
if (begin < 0) {
begin = 0;
}
if (end > this.end) {
end = this.end;
}
this.ensureRange(begin, end); this.ensureRange(begin, end);
return this.bytes.subarray(begin, end); return this.bytes.subarray(begin, end);
} }

View File

@ -598,20 +598,16 @@ class PDFDocument {
idArray[0] !== EMPTY_FINGERPRINT) { idArray[0] !== EMPTY_FINGERPRINT) {
hash = stringToBytes(idArray[0]); hash = stringToBytes(idArray[0]);
} else { } else {
if (this.stream.ensureRange) { hash = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES),
this.stream.ensureRange(0, 0, FINGERPRINT_FIRST_BYTES);
Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end));
}
hash = calculateMD5(this.stream.bytes.subarray(0,
FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
} }
let fingerprint = ''; const fingerprintBuf = [];
for (let i = 0, ii = hash.length; i < ii; i++) { for (let i = 0, ii = hash.length; i < ii; i++) {
const hex = hash[i].toString(16); 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) { _getLinearizationPage(pageIndex) {

View File

@ -19,7 +19,9 @@
* license. * license.
*/ */
import { FormatError, isSpace, stringToBytes } from '../shared/util'; import {
FormatError, isSpace, stringToBytes, unreachable
} from '../shared/util';
import { isDict } from './primitives'; import { isDict } from './primitives';
var Stream = (function StreamClosure() { var Stream = (function StreamClosure() {
@ -92,6 +94,17 @@ var Stream = (function StreamClosure() {
this.pos -= bytes.length; this.pos -= bytes.length;
return bytes; 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) { skip: function Stream_skip(n) {
if (!n) { if (!n) {
n = 1; n = 1;
@ -236,6 +249,11 @@ var DecodeStream = (function DecodeStreamClosure() {
} }
return new Stream(this.buffer, start, length, dict); return new Stream(this.buffer, start, length, dict);
}, },
getByteRange(begin, end) {
unreachable('Should not call DecodeStream.getByteRange');
},
skip: function DecodeStream_skip(n) { skip: function DecodeStream_skip(n) {
if (!n) { if (!n) {
n = 1; n = 1;