From 82b6b4ead85de32a3d57f1b0a6473985181f6785 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Fri, 8 Jul 2011 14:57:40 +0200 Subject: [PATCH 1/4] min. perf. Dict --- pdf.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdf.js b/pdf.js index e332e12e5..f2ea1fd05 100644 --- a/pdf.js +++ b/pdf.js @@ -1943,7 +1943,7 @@ var Dict = (function() { forEach: function(callback) { for (var key in this.map) { - callback.call(null, key, this.map[key]); + callback(key, this.map[key]); } } }; From 4391e2985ae3af82b611ebed76ddf28b6b7435c3 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Fri, 8 Jul 2011 23:19:03 +0200 Subject: [PATCH 2/4] Adding AsciiHexDecode Filter --- pdf.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pdf.js b/pdf.js index f2ea1fd05..563b9ca3f 100644 --- a/pdf.js +++ b/pdf.js @@ -904,6 +904,47 @@ var Ascii85Stream = (function() { return constructor; })(); +var AsciiHexStream = (function() { + function constructor(str) { + this.str = str; + this.dict = str.dict; + + DecodeStream.call(this); + } + + constructor.prototype = Object.create(DecodeStream.prototype); + + constructor.prototype.readBlock = function() { + var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, + decodeLength, buffer, bufferLength, i, length; + + decodeLength = (bytes.length + 1) / 2; + buffer = this.ensureBuffer(this.bufferLength + decodeLength); + bufferLength = this.bufferLength; + + for(i = 0, length = bytes.length; i < length; i++) { + c = String.fromCharCode(bytes[i]); + while (Lexer.isSpace(c) && (i+1) < length) { + c = String.fromCharCode(bytes[++i]); + } + + if((i+1) < length && (bytes[i+1] !== gtCode)) { + n = String.fromCharCode(bytes[++i]); + buffer[bufferLength++] = Number('0x'+c+n); + } else { + if(bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. + buffer[bufferLength++] = Number('0x'+c+'0'); + } + } + } + + this.bufferLength = bufferLength; + this.eof = true; + }; + + return constructor; +})(); + var CCITTFaxStream = (function() { var ccittEOL = -2; @@ -2496,6 +2537,8 @@ var Parser = (function() { return new JpegStream(bytes, stream.dict); } else if (name == 'ASCII85Decode') { return new Ascii85Stream(stream); + } else if (name == 'ASCIIHexDecode') { + return new AsciiHexStream(stream); } else if (name == 'CCITTFaxDecode') { TODO('implement fax stream'); return new CCITTFaxStream(stream, params); From f88d05e3b543ee7637f313912cead9b313b2f7e3 Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Fri, 8 Jul 2011 23:21:14 +0200 Subject: [PATCH 3/4] Adding ASCIIHexDecode pdf to test/pdfs --- test/pdfs/asciihexdecode.pdf | 55 ++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 test/pdfs/asciihexdecode.pdf diff --git a/test/pdfs/asciihexdecode.pdf b/test/pdfs/asciihexdecode.pdf new file mode 100644 index 000000000..f3bd457ec --- /dev/null +++ b/test/pdfs/asciihexdecode.pdf @@ -0,0 +1,55 @@ +%PDF-1.0 +1 0 obj +<< + /Pages 2 0 R + /Type /Catalog +>> +endobj +2 0 obj +<< + /Count 1 + /Kids [ 3 0 R ] + /Type /Pages +>> +endobj +3 0 obj +<< + /MediaBox [ 0 0 795 842 ] + /Parent 2 0 R + /Contents 4 0 R + /Resources << + /Font << + /F1 << + /Name /F1 + /BaseFont /Helvetica + /Subtype /Type1 + /Type /Font + >> + >> + >> + /Type /Page +>> +endobj +4 0 obj +<< + /Filter /ASCIIHexDecode + /Length 111 +>>stream +42540A2F46312033302054660A333530203735302054640A323020544C0A312054720A2848656C6C6F20776F726C642920546A0A45540A> +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000010 00000 n +0000000067 00000 n +0000000136 00000 n +0000000373 00000 n +trailer +<< + /Root 1 0 R + /Size 5 +>> +startxref +568 +%%EOF From ae867e3a9c98dd55d8dbb250771b8ef891b88dcb Mon Sep 17 00:00:00 2001 From: Saebekassebil Date: Sat, 9 Jul 2011 00:30:46 +0200 Subject: [PATCH 4/4] Using map for hex conversion and left-shift for secure division --- pdf.js | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/pdf.js b/pdf.js index 563b9ca3f..69a25f051 100644 --- a/pdf.js +++ b/pdf.js @@ -912,28 +912,55 @@ var AsciiHexStream = (function() { DecodeStream.call(this); } + var hexvalueMap = { + 9: -1, // \t + 32: -1, // space + 48: 0, + 49: 1, + 50: 2, + 51: 3, + 52: 4, + 53: 5, + 54: 6, + 55: 7, + 56: 8, + 57: 9, + 65: 10, + 66: 11, + 67: 12, + 68: 13, + 69: 14, + 70: 15, + 97: 10, + 98: 11, + 99: 12, + 100: 13, + 101: 14, + 102: 15 + }; + constructor.prototype = Object.create(DecodeStream.prototype); constructor.prototype.readBlock = function() { var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, decodeLength, buffer, bufferLength, i, length; - decodeLength = (bytes.length + 1) / 2; + decodeLength = (bytes.length + 1) >> 1; buffer = this.ensureBuffer(this.bufferLength + decodeLength); bufferLength = this.bufferLength; for(i = 0, length = bytes.length; i < length; i++) { - c = String.fromCharCode(bytes[i]); - while (Lexer.isSpace(c) && (i+1) < length) { - c = String.fromCharCode(bytes[++i]); + c = hexvalueMap[bytes[i]]; + while (c == -1 && (i+1) < length) { + c = hexvalueMap[bytes[++i]]; } if((i+1) < length && (bytes[i+1] !== gtCode)) { - n = String.fromCharCode(bytes[++i]); - buffer[bufferLength++] = Number('0x'+c+n); + n = hexvalueMap[bytes[++i]]; + buffer[bufferLength++] = c*16+n; } else { if(bytes[i] !== gtCode) { // EOD marker at an odd number, behave as if a 0 followed the last digit. - buffer[bufferLength++] = Number('0x'+c+'0'); + buffer[bufferLength++] = c*16; } } }