--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -15,18 +15,18 @@
* limitations under the License.
*/
// Initializing PDFJS global object (if still undefined)
if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
-PDFJS.version = '0.8.641';
-PDFJS.build = '19485c3';
+PDFJS.version = '0.8.681';
+PDFJS.build = '48c672b';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
'use strict';
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
@@ -2989,17 +2989,17 @@ var LinkAnnotation = (function LinkAnnot
var dict = params.dict;
var data = this.data;
var action = dict.get('A');
if (action) {
var linkType = action.get('S').name;
if (linkType === 'URI') {
- var url = action.get('URI');
+ var url = addDefaultProtocolToUrl(action.get('URI'));
// TODO: pdf spec mentions urls can be relative to a Base
// entry in the dictionary.
if (!isValidUrl(url, false)) {
url = '';
}
data.url = url;
} else if (linkType === 'GoTo') {
data.dest = action.get('D');
@@ -3025,16 +3025,24 @@ var LinkAnnotation = (function LinkAnnot
}
} else if (dict.has('Dest')) {
// simple destination link
var dest = dict.get('Dest');
data.dest = isName(dest) ? dest.name : dest;
}
}
+ // Lets URLs beginning with 'www.' default to using the 'http://' protocol.
+ function addDefaultProtocolToUrl(url) {
+ if (url.indexOf('www.') === 0) {
+ return ('http://' + url);
+ }
+ return url;
+ }
+
Util.inherit(LinkAnnotation, Annotation, {
hasOperatorList: function LinkAnnotation_hasOperatorList() {
return false;
},
hasHtml: function LinkAnnotation_hasHtml() {
return true;
},
@@ -14904,17 +14912,17 @@ var PartialEvaluator = (function Partial
var flags = properties.flags;
var differences = [];
var baseEncoding = properties.type === 'TrueType' ?
Encodings.WinAnsiEncoding :
Encodings.StandardEncoding;
// The Symbolic attribute can be misused for regular fonts
// Heuristic: we have to check if the font is a standard one also
if (!!(flags & FontFlags.Symbolic)) {
- baseEncoding = !properties.file ? Encodings.symbolsEncoding :
+ baseEncoding = !properties.file ? Encodings.SymbolSetEncoding :
Encodings.MacRomanEncoding;
}
if (dict.has('Encoding')) {
var encoding = dict.get('Encoding');
if (isDict(encoding)) {
var baseName = encoding.get('BaseEncoding');
if (baseName) {
overridableEncoding = false;
@@ -15751,18 +15759,18 @@ var Encodings = {
'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
'ydieresis'],
- symbolsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
- '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
+ SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+ '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
@@ -18602,16 +18610,27 @@ var Font = (function FontClosure() {
charcode: charcode,
glyphId: glyphId
});
}
} else {
error('cmap table has unsupported format: ' + format);
}
+ // removing duplicate entries
+ mappings.sort(function (a, b) {
+ return a.charcode - b.charcode;
+ });
+ for (var i = 1; i < mappings.length; i++) {
+ if (mappings[i - 1].charcode === mappings[i].charcode) {
+ mappings.splice(i, 1);
+ i--;
+ }
+ }
+
return {
platformId: potentialTable.platformId,
encodingId: potentialTable.encodingId,
isSymbolicFont: potentialTable.isSymbolicFont,
mappings: mappings,
hasShortCmap: hasShortCmap
};
}
@@ -18689,16 +18708,20 @@ var Font = (function FontClosure() {
((flag & 4) ? 1 : (flag & 32) ? 0 : 2);
coordinatesLength += xyLength;
if (flag & 8) {
var repeat = glyf[j++];
i += repeat;
coordinatesLength += repeat * xyLength;
}
}
+ // glyph without coordinates will be rejected
+ if (coordinatesLength === 0) {
+ return 0;
+ }
var glyphDataLength = j + coordinatesLength;
if (glyphDataLength > glyf.length) {
// not enough data for coordinates
return 0;
}
if (!hintsValid && instructionsLength > 0) {
dest.set(glyf.subarray(0, instructionsStart), destStart);
dest.set([0, 0], destStart + instructionsStart);
@@ -18787,16 +18810,23 @@ var Font = (function FontClosure() {
return (data[offset] << 9) | (data[offset + 1] << 1);
};
itemEncode = function fontItemEncode(data, offset, value) {
data[offset] = (value >> 9) & 0xFF;
data[offset + 1] = (value >> 1) & 0xFF;
};
}
var locaData = loca.data;
+ var locaDataSize = itemSize * (1 + numGlyphs);
+ // is loca.data too short or long?
+ if (locaData.length !== locaDataSize) {
+ locaData = new Uint8Array(locaDataSize);
+ locaData.set(loca.data.subarray(0, locaDataSize));
+ loca.data = locaData;
+ }
// removing the invalid glyphs
var oldGlyfData = glyf.data;
var oldGlyfDataLength = oldGlyfData.length;
var newGlyfData = new Uint8Array(oldGlyfDataLength);
var startOffset = itemDecode(locaData, 0);
var writeOffset = 0;
itemEncode(locaData, 0, writeOffset);
for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
@@ -18830,19 +18860,17 @@ var Font = (function FontClosure() {
var firstEntryLength = itemDecode(locaData, itemSize);
if (newGlyfData.length > firstEntryLength + writeOffset) {
glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
} else {
glyf.data = new Uint8Array(firstEntryLength + writeOffset);
glyf.data.set(newGlyfData.subarray(0, writeOffset));
}
glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
- loca.data = new Uint8Array(locaData.length + itemSize);
- loca.data.set(locaData);
- itemEncode(loca.data, locaData.length,
+ itemEncode(loca.data, locaData.length - itemSize,
writeOffset + firstEntryLength);
} else {
glyf.data = newGlyfData.subarray(0, writeOffset);
}
}
function readPostScriptTable(post, properties, maxpNumGlyphs) {
var start = (font.start ? font.start : 0) + post.offset;
@@ -19032,16 +19060,21 @@ var Font = (function FontClosure() {
ttContext.functionsUsed[funcId] = true;
if (funcId in ttContext.functionsStackDeltas) {
stack.length += ttContext.functionsStackDeltas[funcId];
} else if (funcId in ttContext.functionsDefined &&
functionsCalled.indexOf(funcId) < 0) {
callstack.push({data: data, i: i, stackTop: stack.length - 1});
functionsCalled.push(funcId);
var pc = ttContext.functionsDefined[funcId];
+ if (!pc) {
+ warn('TT: CALL non-existent function');
+ ttContext.hintsValid = false;
+ return;
+ }
data = pc.data;
i = pc.i;
}
}
} else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF
if (inFDEF || inELSE) {
warn('TT: nested FDEFs not allowed');
tooComplexToFollowFunctions = true;
@@ -19052,16 +19085,21 @@ var Font = (function FontClosure() {
var funcId = stack.pop();
ttContext.functionsDefined[funcId] = {data: data, i: i};
} else if (op === 0x2D) { // ENDF - end of function
if (inFDEF) {
inFDEF = false;
lastEndf = i;
} else {
var pc = callstack.pop();
+ if (!pc) {
+ warn('TT: ENDF bad stack');
+ ttContext.hintsValid = false;
+ return;
+ }
var funcId = functionsCalled.pop();
data = pc.data;
i = pc.i;
ttContext.functionsStackDeltas[funcId] =
stack.length - pc.stackTop;
}
} else if (op === 0x89) { // IDEF - instruction definition
if (inFDEF || inELSE) {
@@ -19151,33 +19189,38 @@ var Font = (function FontClosure() {
result.set(content[j], pos);
pos += content[j].length;
}
table.data = result;
table.length = newLength;
}
}
- function sanitizeTTPrograms(fpgm, prep) {
+ function sanitizeTTPrograms(fpgm, prep, cvt) {
var ttContext = {
functionsDefined: [],
functionsUsed: [],
functionsStackDeltas: [],
tooComplexToFollowFunctions: false,
hintsValid: true
};
if (fpgm) {
sanitizeTTProgram(fpgm, ttContext);
}
if (prep) {
sanitizeTTProgram(prep, ttContext);
}
if (fpgm) {
checkInvalidFunctions(ttContext, maxFunctionDefs);
}
+ if (cvt && (cvt.length & 1)) {
+ var cvtData = new Uint8Array(cvt.length + 1);
+ cvtData.set(cvt.data);
+ cvt.data = cvtData;
+ }
return ttContext.hintsValid;
}
// The following steps modify the original font data, making copy
font = new Stream(new Uint8Array(font.getBytes()));
var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp',
'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
@@ -19187,16 +19230,19 @@ var Font = (function FontClosure() {
var tables = { 'OS/2': null, cmap: null, head: null, hhea: null,
hmtx: null, maxp: null, name: null, post: null};
for (var i = 0; i < numTables; i++) {
var table = readTableEntry(font);
if (VALID_TABLES.indexOf(table.tag) < 0) {
continue; // skipping table if it's not a required or optional table
}
+ if (table.length === 0) {
+ continue; // skipping empty tables
+ }
tables[table.tag] = table;
}
var isTrueType = !tables['CFF '];
if (!isTrueType) {
// OpenType font
if (!tables.head || !tables.hhea || !tables.maxp || !tables.post) {
// no major tables: throwing everything at CFFFont
@@ -19221,35 +19267,43 @@ var Font = (function FontClosure() {
error('Required "maxp" table is not found');
}
font.pos = (font.start || 0) + tables.maxp.offset;
var version = int32(font.getBytes(4));
var numGlyphs = int16(font.getBytes(2));
var maxFunctionDefs = 0;
if (version >= 0x00010000 && tables.maxp.length >= 22) {
- font.pos += 14;
+ // maxZones can be invalid
+ font.pos += 8;
+ var maxZones = int16(font.getBytes(2));
+ if (maxZones > 2) { // reset to 2 if font has invalid maxZones
+ tables.maxp.data[14] = 0;
+ tables.maxp.data[15] = 2;
+ }
+ font.pos += 4;
maxFunctionDefs = int16(font.getBytes(2));
}
var dupFirstEntry = false;
if (properties.type == 'CIDFontType2' && properties.toUnicode &&
properties.toUnicode[0] > '\u0000') {
// oracle's defect (see 3427), duplicating first entry
dupFirstEntry = true;
numGlyphs++;
tables.maxp.data[4] = numGlyphs >> 8;
tables.maxp.data[5] = numGlyphs & 255;
}
var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep,
- maxFunctionDefs);
+ tables['cvt '], maxFunctionDefs);
if (!hintsValid) {
delete tables.fpgm;
delete tables.prep;
+ delete tables['cvt '];
}
// Tables needs to be written by ascendant alphabetic order
var tablesNames = Object.keys(tables);
tablesNames.sort();
numTables = tablesNames.length;
@@ -19273,17 +19327,16 @@ var Font = (function FontClosure() {
error('Required "head" table is not found');
}
sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);
if (isTrueType) {
var isGlyphLocationsLong = int16([tables.head.data[50],
tables.head.data[51]]);
-
sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs,
isGlyphLocationsLong, hintsValid, dupFirstEntry);
}
if (!tables.hhea) {
error('Required "hhea" table is not found');
}
@@ -20077,18 +20130,20 @@ var Font = (function FontClosure() {
while (i < chars.length) {
var c = this.cmap.readCharCode(chars, i);
var charcode = c[0];
var length = c[1];
i += length;
var glyph = this.charToGlyph(charcode);
glyphs.push(glyph);
// placing null after each word break charcode (ASCII SPACE)
- if (charcode == 0x20)
+ // Ignore occurences of 0x20 in multiple-byte codes.
+ if (length === 1 && chars.charCodeAt(i - 1) === 0x20) {
glyphs.push(null);
+ }
}
}
else {
for (var i = 0, ii = chars.length; i < ii; ++i) {
var charcode = chars.charCodeAt(i);
var glyph = this.charToGlyph(charcode);
glyphs.push(glyph);
if (charcode == 0x20)
@@ -20720,30 +20775,45 @@ var Type1Parser = (function Type1ParserC
encoding = Encodings[encodingArg];
} else {
encoding = [];
var size = parseInt(encodingArg, 10) | 0;
this.getToken(); // read in 'array'
for (var j = 0; j < size; j++) {
var token = this.getToken();
- if (token === 'dup') {
- var index = this.readInt();
- this.getToken(); // read in '/'
- var glyph = this.getToken();
- encoding[index] = glyph;
- this.getToken(); // read the in 'put'
+ // skipping till first dup or def (e.g. ignoring for statement)
+ while (token !== 'dup' && token !== 'def') {
+ token = this.getToken();
+ if (token === null) {
+ return; // invalid header
+ }
}
+ if (token === 'def') {
+ break; // read all array data
+ }
+ var index = this.readInt();
+ this.getToken(); // read in '/'
+ var glyph = this.getToken();
+ encoding[index] = glyph;
+ this.getToken(); // read the in 'put'
}
}
if (properties.overridableEncoding && encoding) {
properties.baseEncoding = encoding;
break;
}
break;
+ case 'FontBBox':
+ var fontBBox = this.readNumberArray();
+ // adjusting ascent/descent
+ properties.ascent = fontBBox[3];
+ properties.descent = fontBBox[1];
+ properties.ascentScaled = true;
+ break;
}
}
}
};
return Type1Parser;
})();
@@ -20816,23 +20886,43 @@ var CFFStandardStrings = [
'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall',
'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall',
'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003',
'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'
];
// Type1Font is also a CIDFontType0.
var Type1Font = function Type1Font(name, file, properties) {
+ // Some bad generators embed pfb file as is, we have to strip 6-byte headers.
+ // Also, length1 and length2 might be off by 6 bytes as well.
+ // http://www.math.ubc.ca/~cass/piscript/type1.pdf
+ var PFB_HEADER_SIZE = 6;
+ var headerBlockLength = properties.length1;
+ var eexecBlockLength = properties.length2;
+ var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
+ var pfbHeaderPresent = pfbHeader[0] == 0x80 && pfbHeader[1] == 0x01;
+ if (pfbHeaderPresent) {
+ file.skip(PFB_HEADER_SIZE);
+ headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
+ (pfbHeader[3] << 8) | pfbHeader[2];
+ }
+
// Get the data block containing glyphs and subrs informations
- var headerBlock = new Stream(file.getBytes(properties.length1));
+ var headerBlock = new Stream(file.getBytes(headerBlockLength));
var headerBlockParser = new Type1Parser(headerBlock);
headerBlockParser.extractFontHeader(properties);
+ if (pfbHeaderPresent) {
+ pfbHeader = file.getBytes(PFB_HEADER_SIZE);
+ eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
+ (pfbHeader[3] << 8) | pfbHeader[2];
+ }
+
// Decrypt the data blocks and retrieve it's content
- var eexecBlock = new Stream(file.getBytes(properties.length2));
+ var eexecBlock = new Stream(file.getBytes(eexecBlockLength));
var eexecBlockParser = new Type1Parser(eexecBlock, true);
var data = eexecBlockParser.extractFontProgram();
for (var info in data.properties)
properties[info] = data.properties[info];
var charstrings = this.getOrderedCharStrings(data.charstrings, properties);
var type2Charstrings = this.getType2Charstrings(charstrings);
var subrs = this.getType2Subrs(data.subrs);