From 0e33eb6e133eef69f1ac45a8700642d82ca8633f Mon Sep 17 00:00:00 2001 From: SheetJS Date: Thu, 31 Mar 2022 04:57:58 -0400 Subject: [PATCH] unify changes with main sheetjs project - Fixed issue #14 h/t @wisekaa03 - CFB write truncate file names exceeding 32 characters Co-authored-by: Stanislav Vyaliy --- bits/04_base64.js | 80 +++++++------- bits/21_crc32.js | 122 ++++++++++----------- bits/30_cfbheader.js | 2 +- bits/45_readfat.js | 2 +- bits/49_readutils.js | 2 +- bits/56_dirtree.js | 8 +- bits/61_layout.js | 1 - bits/66_dir.js | 4 + bits/77_writeutils.js | 2 +- bits/80_deflate.js | 9 +- bits/81_inflate.js | 15 ++- bits/84_mht.js | 4 +- cfb.js | 242 ++++++++++++++++++++---------------------- 13 files changed, 242 insertions(+), 251 deletions(-) diff --git a/bits/04_base64.js b/bits/04_base64.js index a334d48..9830b42 100644 --- a/bits/04_base64.js +++ b/bits/04_base64.js @@ -1,44 +1,36 @@ -var Base64 = (function make_b64(){ - var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - return { - encode: function(input/*:string*/)/*:string*/ { - var o = ""; - var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0; - for(var i = 0; i < input.length; ) { - c1 = input.charCodeAt(i++); - e1 = (c1 >> 2); - - c2 = input.charCodeAt(i++); - e2 = ((c1 & 3) << 4) | (c2 >> 4); - - c3 = input.charCodeAt(i++); - e3 = ((c2 & 15) << 2) | (c3 >> 6); - e4 = (c3 & 63); - if (isNaN(c2)) { e3 = e4 = 64; } - else if (isNaN(c3)) { e4 = 64; } - o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4); - } - return o; - }, - decode: function b64_decode(input/*:string*/)/*:string*/ { - var o = ""; - var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0; - input = input.replace(/[^\w\+\/\=]/g, ""); - for(var i = 0; i < input.length;) { - e1 = map.indexOf(input.charAt(i++)); - e2 = map.indexOf(input.charAt(i++)); - c1 = (e1 << 2) | (e2 >> 4); - o += String.fromCharCode(c1); - - e3 = map.indexOf(input.charAt(i++)); - c2 = ((e2 & 15) << 4) | (e3 >> 2); - if (e3 !== 64) { o += String.fromCharCode(c2); } - - e4 = map.indexOf(input.charAt(i++)); - c3 = ((e3 & 3) << 6) | e4; - if (e4 !== 64) { o += String.fromCharCode(c3); } - } - return o; - } - }; -})(); +var Base64_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +function Base64_encode(input/*:string*/)/*:string*/ { + var o = ""; + var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0; + for (var i = 0; i < input.length; ) { + c1 = input.charCodeAt(i++); + e1 = (c1 >> 2); + c2 = input.charCodeAt(i++); + e2 = ((c1 & 3) << 4) | (c2 >> 4); + c3 = input.charCodeAt(i++); + e3 = ((c2 & 15) << 2) | (c3 >> 6); + e4 = (c3 & 63); + if (isNaN(c2)) e3 = e4 = 64; + else if (isNaN(c3)) e4 = 64; + o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4); + } + return o; +} +function Base64_decode(input/*:string*/)/*:string*/ { + var o = ""; + var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0; + input = input.replace(/[^\w\+\/\=]/g, ""); + for (var i = 0; i < input.length;) { + e1 = Base64_map.indexOf(input.charAt(i++)); + e2 = Base64_map.indexOf(input.charAt(i++)); + c1 = (e1 << 2) | (e2 >> 4); + o += String.fromCharCode(c1); + e3 = Base64_map.indexOf(input.charAt(i++)); + c2 = ((e2 & 15) << 4) | (e3 >> 2); + if (e3 !== 64) o += String.fromCharCode(c2); + e4 = Base64_map.indexOf(input.charAt(i++)); + c3 = ((e3 & 3) << 6) | e4; + if (e4 !== 64) o += String.fromCharCode(c3); + } + return o; +} diff --git a/bits/21_crc32.js b/bits/21_crc32.js index cc86b0f..96a848b 100644 --- a/bits/21_crc32.js +++ b/bits/21_crc32.js @@ -1,18 +1,15 @@ -/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ +/*! crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ /* vim: set ts=2: */ /*exported CRC32 */ -var CRC32; -(function (factory) { - /*jshint ignore:start */ - /*eslint-disable */ - factory(CRC32 = {}); - /*eslint-enable */ - /*jshint ignore:end */ -}(function(CRC32) { -CRC32.version = '1.2.0'; -/* see perf/crc32table.js */ +var CRC32 = /*#__PURE__*/(function() { +var CRC32 = {}; +CRC32.version = '1.2.1'; +/*:: +type ABuf = Array | Buffer | Uint8Array; +type CRC32TableType = Array | Int32Array; +*/ /*global Int32Array */ -function signed_crc_table()/*:any*/ { +function signed_crc_table()/*:CRC32TableType*/ { var c = 0, table/*:Array*/ = new Array(256); for(var n =0; n != 256; ++n){ @@ -31,71 +28,70 @@ function signed_crc_table()/*:any*/ { return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table; } -var T = signed_crc_table(); -function crc32_bstr(bstr/*:string*/, seed/*:number*/)/*:number*/ { - var C = seed ^ -1, L = bstr.length - 1; - for(var i = 0; i < L;) { - C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; - C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; +var T0 = signed_crc_table(); +function slice_by_16_tables(T) { + var c = 0, v = 0, n = 0, table/*:Array*/ = typeof Int32Array !== 'undefined' ? new Int32Array(4096) : new Array(4096) ; + + for(n = 0; n != 256; ++n) table[n] = T[n]; + for(n = 0; n != 256; ++n) { + v = T[n]; + for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF]; } - if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF]; - return C ^ -1; + var out = []; + for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256); + return out; +} +var TT = slice_by_16_tables(T0); +var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4]; +var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9]; +var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14]; +function crc32_bstr(bstr/*:string*/, seed/*:?number*/)/*:number*/ { + var C = seed/*:: ? 0 : 0 */ ^ -1; + for(var i = 0, L = bstr.length; i < L;) C = (C>>>8) ^ T0[(C^bstr.charCodeAt(i++))&0xFF]; + return ~C; } -function crc32_buf(buf/*:Uint8Array|Array*/, seed/*:number*/)/*:number*/ { - if(buf.length > 10000) return crc32_buf_8(buf, seed); - var C = seed ^ -1, L = buf.length - 3; - for(var i = 0; i < L;) { - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - } - while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - return C ^ -1; +function crc32_buf(B/*:ABuf*/, seed/*:?number*/)/*:number*/ { + var C = seed/*:: ? 0 : 0 */ ^ -1, L = B.length - 15, i = 0; + for(; i < L;) C = + Tf[B[i++] ^ (C & 255)] ^ + Te[B[i++] ^ ((C >> 8) & 255)] ^ + Td[B[i++] ^ ((C >> 16) & 255)] ^ + Tc[B[i++] ^ (C >>> 24)] ^ + Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^ + T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^ + T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]]; + L += 15; + while(i < L) C = (C>>>8) ^ T0[(C^B[i++])&0xFF]; + return ~C; } -function crc32_buf_8(buf/*:Uint8Array|Array*/, seed/*:number*/)/*:number*/ { - var C = seed ^ -1, L = buf.length - 7; - for(var i = 0; i < L;) { - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - } - while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - return C ^ -1; -} - -function crc32_str(str/*:string*/, seed/*:number*/)/*:number*/ { - var C = seed ^ -1; - for(var i = 0, L=str.length, c, d; i < L;) { +function crc32_str(str/*:string*/, seed/*:?number*/)/*:number*/ { + var C = seed/*:: ? 0 : 0 */ ^ -1; + for(var i = 0, L = str.length, c = 0, d = 0; i < L;) { c = str.charCodeAt(i++); if(c < 0x80) { - C = (C>>>8) ^ T[(C ^ c)&0xFF]; + C = (C>>>8) ^ T0[(C^c)&0xFF]; } else if(c < 0x800) { - C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (192|((c>>6)&31)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF]; } else if(c >= 0xD800 && c < 0xE000) { c = (c&1023)+64; d = str.charCodeAt(i++)&1023; - C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (240|((c>>8)&7)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((c>>2)&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(d&63)))&0xFF]; } else { - C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (224|((c>>12)&15)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((c>>6)&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF]; } } - return C ^ -1; + return ~C; } -CRC32.table = T; +CRC32.table = T0; CRC32.bstr = crc32_bstr; CRC32.buf = crc32_buf; CRC32.str = crc32_str; -})); +return CRC32; +})(); diff --git a/bits/30_cfbheader.js b/bits/30_cfbheader.js index 8f9c004..f4971c9 100644 --- a/bits/30_cfbheader.js +++ b/bits/30_cfbheader.js @@ -1,3 +1,3 @@ /* [MS-CFB] v20171201 */ -var CFB = (function _CFB(){ +var CFB = /*#__PURE__*/(function _CFB(){ var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; diff --git a/bits/45_readfat.js b/bits/45_readfat.js index b1b4f5d..b72a13c 100644 --- a/bits/45_readfat.js +++ b/bits/45_readfat.js @@ -11,7 +11,7 @@ function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array*/, if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break; fat_addrs.push(q); } - sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs); + if(cnt >= 1) sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs); } } diff --git a/bits/49_readutils.js b/bits/49_readutils.js index 3508016..bf6d1f6 100644 --- a/bits/49_readutils.js +++ b/bits/49_readutils.js @@ -10,7 +10,7 @@ function read(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) { } switch(type || "base64") { case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return read_file(blob, options); - case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64.decode(blob)), options); + case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64_decode(blob)), options); case "binary": /*:: if(typeof blob !== 'string') throw "Must pass a binary string when type='file'"; */return parse(s2a(blob), options); } return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options); diff --git a/bits/56_dirtree.js b/bits/56_dirtree.js index d23d961..4f2ece3 100644 --- a/bits/56_dirtree.js +++ b/bits/56_dirtree.js @@ -10,7 +10,9 @@ for(i = 0; i < data.length; ++i) { var dad = dirname(data[i][0]); s = fullPaths[dad]; - if(!s) { + while(!s) { + while(dirname(dad) && !fullPaths[dirname(dad)]) dad = dirname(dad); + data.push([dad, ({ name: filename(dad).replace("/",""), type: 1, @@ -18,8 +20,12 @@ ct: now, mt: now, content: null }/*:any*/)]); + // Add name to set fullPaths[dad] = true; + + dad = dirname(data[i][0]); + s = fullPaths[dad]; } } diff --git a/bits/61_layout.js b/bits/61_layout.js index fe6089c..9c52ba5 100644 --- a/bits/61_layout.js +++ b/bits/61_layout.js @@ -3,7 +3,6 @@ for(var i = 0; i < cfb.FileIndex.length; ++i) { var file = cfb.FileIndex[i]; if(!file.content) continue; - /*:: if(file.content == null) throw new Error("unreachable"); */ var flen = file.content.length; if(flen > 0){ if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6; diff --git a/bits/66_dir.js b/bits/66_dir.js index 3607266..4ef383c 100644 --- a/bits/66_dir.js +++ b/bits/66_dir.js @@ -9,6 +9,10 @@ file = cfb.FileIndex[i]; if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN; var _nm/*:string*/ = (i === 0 && _opts.root) || file.name; + if(_nm.length > 32) { + console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32)); + _nm = _nm.slice(0, 32); + } flen = 2*(_nm.length+1); o.write_shift(64, _nm, "utf16le"); o.write_shift(2, flen); diff --git a/bits/77_writeutils.js b/bits/77_writeutils.js index 3ebb9d2..c155f0f 100644 --- a/bits/77_writeutils.js +++ b/bits/77_writeutils.js @@ -16,7 +16,7 @@ function write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string switch(options && options.type || "buffer") { case "file": get_fs(); fs.writeFileSync(options.filename, (o/*:any*/)); return o; case "binary": return typeof o == "string" ? o : a2s(o); - case "base64": return Base64.encode(typeof o == "string" ? o : a2s(o)); + case "base64": return Base64_encode(typeof o == "string" ? o : a2s(o)); case "buffer": if(has_buf) return Buffer.isBuffer(o) ? o : Buffer_from(o); /* falls through */ case "array": return typeof o == "string" ? s2a(o) : o; diff --git a/bits/80_deflate.js b/bits/80_deflate.js index ec27913..4586228 100644 --- a/bits/80_deflate.js +++ b/bits/80_deflate.js @@ -1,12 +1,13 @@ -var _deflateRaw = (function() { +var _deflateRaw = /*#__PURE__*/(function _deflateRawIIFE() { var DST_LN_RE = use_typed_arrays ? new Uint8Array(0x8000) : []; - for(var j = 0, k = 0; j < DST_LN.length; ++j) { + var j = 0, k = 0; + for(; j < DST_LN.length - 1; ++j) { for(; k < DST_LN[j+1]; ++k) DST_LN_RE[k] = j; } for(;k < 32768; ++k) DST_LN_RE[k] = 29; - var LEN_LN_RE = use_typed_arrays ? new Uint8Array(0x102) : []; - for(j = 0, k = 0; j < LEN_LN.length; ++j) { + var LEN_LN_RE = use_typed_arrays ? new Uint8Array(0x103) : []; + for(j = 0, k = 0; j < LEN_LN.length - 1; ++j) { for(; k < LEN_LN[j+1]; ++k) LEN_LN_RE[k] = j; } diff --git a/bits/81_inflate.js b/bits/81_inflate.js index 4580e70..762dc4d 100644 --- a/bits/81_inflate.js +++ b/bits/81_inflate.js @@ -103,14 +103,12 @@ function inflate(data, usz/*:number*/) { var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8; boff += 32; /* push sz bytes */ - if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; } - if(typeof data.copy === 'function') { - // $FlowIgnore - data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz); - woff += sz; boff += 8*sz; - } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; } + if(sz > 0) { + if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; } + while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; } + } continue; - } else if((header >>> 1) == 1) { + } else if((header >> 1) == 1) { /* Fixed Huffman */ max_len_1 = 9; max_len_2 = 5; } else { @@ -155,7 +153,8 @@ function inflate(data, usz/*:number*/) { } } } - return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3]; + if(usz) return [outbuf, (boff+7)>>>3]; + return [outbuf.slice(0, woff), (boff+7)>>>3]; } function _inflate(payload, usz) { diff --git a/bits/84_mht.js b/bits/84_mht.js index e195562..edac5fa 100644 --- a/bits/84_mht.js +++ b/bits/84_mht.js @@ -27,7 +27,7 @@ function get_content_type(fi/*:CFBEntry*/, fp/*:string*/)/*:string*/ { /* 76 character chunks TODO: intertwine encoding */ function write_base64_76(bstr/*:string*/)/*:string*/ { - var data = Base64.encode(bstr); + var data = Base64_encode(bstr); var o = []; for(var i = 0; i < data.length; i+= 76) o.push(data.slice(i, i+76)); return o.join("\r\n") + "\r\n"; @@ -108,7 +108,7 @@ function parse_mime(cfb/*:CFBContainer*/, data/*:Array*/, root/*:string* } ++di; switch(cte.toLowerCase()) { - case 'base64': fdata = s2a(Base64.decode(data.slice(di).join(""))); break; + case 'base64': fdata = s2a(Base64_decode(data.slice(di).join(""))); break; case 'quoted-printable': fdata = parse_quoted_printable(data.slice(di)); break; default: throw new Error("Unsupported Content-Transfer-Encoding " + cte); } diff --git a/cfb.js b/cfb.js index fb58011..8f168e7 100644 --- a/cfb.js +++ b/cfb.js @@ -4,50 +4,42 @@ /*exported CFB */ /*global module, require:false, process:false, Buffer:false, Uint8Array:false, Uint16Array:false */ -var Base64 = (function make_b64(){ - var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - return { - encode: function(input) { - var o = ""; - var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0; - for(var i = 0; i < input.length; ) { - c1 = input.charCodeAt(i++); - e1 = (c1 >> 2); - - c2 = input.charCodeAt(i++); - e2 = ((c1 & 3) << 4) | (c2 >> 4); - - c3 = input.charCodeAt(i++); - e3 = ((c2 & 15) << 2) | (c3 >> 6); - e4 = (c3 & 63); - if (isNaN(c2)) { e3 = e4 = 64; } - else if (isNaN(c3)) { e4 = 64; } - o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4); - } - return o; - }, - decode: function b64_decode(input) { - var o = ""; - var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0; - input = input.replace(/[^\w\+\/\=]/g, ""); - for(var i = 0; i < input.length;) { - e1 = map.indexOf(input.charAt(i++)); - e2 = map.indexOf(input.charAt(i++)); - c1 = (e1 << 2) | (e2 >> 4); - o += String.fromCharCode(c1); - - e3 = map.indexOf(input.charAt(i++)); - c2 = ((e2 & 15) << 4) | (e3 >> 2); - if (e3 !== 64) { o += String.fromCharCode(c2); } - - e4 = map.indexOf(input.charAt(i++)); - c3 = ((e3 & 3) << 6) | e4; - if (e4 !== 64) { o += String.fromCharCode(c3); } - } - return o; - } - }; -})(); +var Base64_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; +function Base64_encode(input) { + var o = ""; + var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0; + for (var i = 0; i < input.length; ) { + c1 = input.charCodeAt(i++); + e1 = (c1 >> 2); + c2 = input.charCodeAt(i++); + e2 = ((c1 & 3) << 4) | (c2 >> 4); + c3 = input.charCodeAt(i++); + e3 = ((c2 & 15) << 2) | (c3 >> 6); + e4 = (c3 & 63); + if (isNaN(c2)) e3 = e4 = 64; + else if (isNaN(c3)) e4 = 64; + o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4); + } + return o; +} +function Base64_decode(input) { + var o = ""; + var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0; + input = input.replace(/[^\w\+\/\=]/g, ""); + for (var i = 0; i < input.length;) { + e1 = Base64_map.indexOf(input.charAt(i++)); + e2 = Base64_map.indexOf(input.charAt(i++)); + c1 = (e1 << 2) | (e2 >> 4); + o += String.fromCharCode(c1); + e3 = Base64_map.indexOf(input.charAt(i++)); + c2 = ((e2 & 15) << 4) | (e3 >> 2); + if (e3 !== 64) o += String.fromCharCode(c2); + e4 = Base64_map.indexOf(input.charAt(i++)); + c3 = ((e3 & 3) << 6) | e4; + if (e4 !== 64) o += String.fromCharCode(c3); + } + return o; +} var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && process.versions.node); var Buffer_from = function(){}; @@ -173,19 +165,12 @@ function new_buf(sz) { return o; } -/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ +/*! crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ /* vim: set ts=2: */ /*exported CRC32 */ -var CRC32; -(function (factory) { - /*jshint ignore:start */ - /*eslint-disable */ - factory(CRC32 = {}); - /*eslint-enable */ - /*jshint ignore:end */ -}(function(CRC32) { -CRC32.version = '1.2.0'; -/* see perf/crc32table.js */ +var CRC32 = (function() { +var CRC32 = {}; +CRC32.version = '1.2.1'; /*global Int32Array */ function signed_crc_table() { var c = 0, table = new Array(256); @@ -206,74 +191,73 @@ function signed_crc_table() { return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table; } -var T = signed_crc_table(); +var T0 = signed_crc_table(); +function slice_by_16_tables(T) { + var c = 0, v = 0, n = 0, table = typeof Int32Array !== 'undefined' ? new Int32Array(4096) : new Array(4096) ; + + for(n = 0; n != 256; ++n) table[n] = T[n]; + for(n = 0; n != 256; ++n) { + v = T[n]; + for(c = 256 + n; c < 4096; c += 256) v = table[c] = (v >>> 8) ^ T[v & 0xFF]; + } + var out = []; + for(n = 1; n != 16; ++n) out[n - 1] = typeof Int32Array !== 'undefined' ? table.subarray(n * 256, n * 256 + 256) : table.slice(n * 256, n * 256 + 256); + return out; +} +var TT = slice_by_16_tables(T0); +var T1 = TT[0], T2 = TT[1], T3 = TT[2], T4 = TT[3], T5 = TT[4]; +var T6 = TT[5], T7 = TT[6], T8 = TT[7], T9 = TT[8], Ta = TT[9]; +var Tb = TT[10], Tc = TT[11], Td = TT[12], Te = TT[13], Tf = TT[14]; function crc32_bstr(bstr, seed) { - var C = seed ^ -1, L = bstr.length - 1; - for(var i = 0; i < L;) { - C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; - C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; - } - if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF]; - return C ^ -1; + var C = seed ^ -1; + for(var i = 0, L = bstr.length; i < L;) C = (C>>>8) ^ T0[(C^bstr.charCodeAt(i++))&0xFF]; + return ~C; } -function crc32_buf(buf, seed) { - if(buf.length > 10000) return crc32_buf_8(buf, seed); - var C = seed ^ -1, L = buf.length - 3; - for(var i = 0; i < L;) { - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - } - while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - return C ^ -1; -} - -function crc32_buf_8(buf, seed) { - var C = seed ^ -1, L = buf.length - 7; - for(var i = 0; i < L;) { - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - } - while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; - return C ^ -1; +function crc32_buf(B, seed) { + var C = seed ^ -1, L = B.length - 15, i = 0; + for(; i < L;) C = + Tf[B[i++] ^ (C & 255)] ^ + Te[B[i++] ^ ((C >> 8) & 255)] ^ + Td[B[i++] ^ ((C >> 16) & 255)] ^ + Tc[B[i++] ^ (C >>> 24)] ^ + Tb[B[i++]] ^ Ta[B[i++]] ^ T9[B[i++]] ^ T8[B[i++]] ^ + T7[B[i++]] ^ T6[B[i++]] ^ T5[B[i++]] ^ T4[B[i++]] ^ + T3[B[i++]] ^ T2[B[i++]] ^ T1[B[i++]] ^ T0[B[i++]]; + L += 15; + while(i < L) C = (C>>>8) ^ T0[(C^B[i++])&0xFF]; + return ~C; } function crc32_str(str, seed) { var C = seed ^ -1; - for(var i = 0, L=str.length, c, d; i < L;) { + for(var i = 0, L = str.length, c = 0, d = 0; i < L;) { c = str.charCodeAt(i++); if(c < 0x80) { - C = (C>>>8) ^ T[(C ^ c)&0xFF]; + C = (C>>>8) ^ T0[(C^c)&0xFF]; } else if(c < 0x800) { - C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (192|((c>>6)&31)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF]; } else if(c >= 0xD800 && c < 0xE000) { c = (c&1023)+64; d = str.charCodeAt(i++)&1023; - C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (240|((c>>8)&7)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((c>>2)&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(d&63)))&0xFF]; } else { - C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF]; - C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (224|((c>>12)&15)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|((c>>6)&63)))&0xFF]; + C = (C>>>8) ^ T0[(C ^ (128|(c&63)))&0xFF]; } } - return C ^ -1; + return ~C; } -CRC32.table = T; +CRC32.table = T0; CRC32.bstr = crc32_bstr; CRC32.buf = crc32_buf; CRC32.str = crc32_str; -})); +return CRC32; +})(); /* [MS-CFB] v20171201 */ var CFB = (function _CFB(){ var exports = {}; @@ -577,7 +561,7 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break; fat_addrs.push(q); } - sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs); + if(cnt >= 1) sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs); } } @@ -695,7 +679,7 @@ function read(blob, options) { } switch(type || "base64") { case "file": return read_file(blob, options); - case "base64": return parse(s2a(Base64.decode(blob)), options); + case "base64": return parse(s2a(Base64_decode(blob)), options); case "binary": return parse(s2a(blob), options); } return parse(blob, options); @@ -753,7 +737,9 @@ function rebuild_cfb(cfb, f) { for(i = 0; i < data.length; ++i) { var dad = dirname(data[i][0]); s = fullPaths[dad]; - if(!s) { + while(!s) { + while(dirname(dad) && !fullPaths[dirname(dad)]) dad = dirname(dad); + data.push([dad, ({ name: filename(dad).replace("/",""), type: 1, @@ -761,8 +747,12 @@ function rebuild_cfb(cfb, f) { ct: now, mt: now, content: null })]); + // Add name to set fullPaths[dad] = true; + + dad = dirname(data[i][0]); + s = fullPaths[dad]; } } @@ -810,7 +800,7 @@ function _write(cfb, options) { for(var i = 0; i < cfb.FileIndex.length; ++i) { var file = cfb.FileIndex[i]; if(!file.content) continue; -var flen = file.content.length; + var flen = file.content.length; if(flen > 0){ if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6; else fat_size += (flen + 0x01FF) >> 9; @@ -898,6 +888,10 @@ flen = file.content.length; file = cfb.FileIndex[i]; if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN; var _nm = (i === 0 && _opts.root) || file.name; + if(_nm.length > 32) { + console.error("Name " + _nm + " will be truncated to " + _nm.slice(0,32)); + _nm = _nm.slice(0, 32); + } flen = 2*(_nm.length+1); o.write_shift(64, _nm, "utf16le"); o.write_shift(2, flen); @@ -1012,7 +1006,7 @@ function write(cfb, options) { switch(options && options.type || "buffer") { case "file": get_fs(); fs.writeFileSync(options.filename, (o)); return o; case "binary": return typeof o == "string" ? o : a2s(o); - case "base64": return Base64.encode(typeof o == "string" ? o : a2s(o)); + case "base64": return Base64_encode(typeof o == "string" ? o : a2s(o)); case "buffer": if(has_buf) return Buffer.isBuffer(o) ? o : Buffer_from(o); /* falls through */ case "array": return typeof o == "string" ? s2a(o) : o; @@ -1202,15 +1196,16 @@ if(!use_typed_arrays) { for(; i<=279; i++) clens.push(7); for(; i<=287; i++) clens.push(8); build_tree(clens, fix_lmap, 288); -})();var _deflateRaw = (function() { +})();var _deflateRaw = (function _deflateRawIIFE() { var DST_LN_RE = use_typed_arrays ? new Uint8Array(0x8000) : []; - for(var j = 0, k = 0; j < DST_LN.length; ++j) { + var j = 0, k = 0; + for(; j < DST_LN.length - 1; ++j) { for(; k < DST_LN[j+1]; ++k) DST_LN_RE[k] = j; } for(;k < 32768; ++k) DST_LN_RE[k] = 29; - var LEN_LN_RE = use_typed_arrays ? new Uint8Array(0x102) : []; - for(j = 0, k = 0; j < LEN_LN.length; ++j) { + var LEN_LN_RE = use_typed_arrays ? new Uint8Array(0x103) : []; + for(j = 0, k = 0; j < LEN_LN.length - 1; ++j) { for(; k < LEN_LN[j+1]; ++k) LEN_LN_RE[k] = j; } @@ -1423,14 +1418,12 @@ function inflate(data, usz) { var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8; boff += 32; /* push sz bytes */ - if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; } - if(typeof data.copy === 'function') { - // $FlowIgnore - data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz); - woff += sz; boff += 8*sz; - } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; } + if(sz > 0) { + if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; } + while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; } + } continue; - } else if((header >>> 1) == 1) { + } else if((header >> 1) == 1) { /* Fixed Huffman */ max_len_1 = 9; max_len_2 = 5; } else { @@ -1475,7 +1468,8 @@ function inflate(data, usz) { } } } - return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3]; + if(usz) return [outbuf, (boff+7)>>>3]; + return [outbuf.slice(0, woff), (boff+7)>>>3]; } function _inflate(payload, usz) { @@ -1722,7 +1716,7 @@ function get_content_type(fi, fp) { /* 76 character chunks TODO: intertwine encoding */ function write_base64_76(bstr) { - var data = Base64.encode(bstr); + var data = Base64_encode(bstr); var o = []; for(var i = 0; i < data.length; i+= 76) o.push(data.slice(i, i+76)); return o.join("\r\n") + "\r\n"; @@ -1783,7 +1777,7 @@ function parse_quoted_printable(data) { } /* decode */ - for(var oi = 0; oi < o.length; ++oi) o[oi] = o[oi].replace(/=[0-9A-Fa-f]{2}/g, function($$) { return String.fromCharCode(parseInt($$.slice(1), 16)); }); + for(var oi = 0; oi < o.length; ++oi) o[oi] = o[oi].replace(/[=][0-9A-Fa-f]{2}/g, function($$) { return String.fromCharCode(parseInt($$.slice(1), 16)); }); return s2a(o.join("\r\n")); } @@ -1803,7 +1797,7 @@ function parse_mime(cfb, data, root) { } ++di; switch(cte.toLowerCase()) { - case 'base64': fdata = s2a(Base64.decode(data.slice(di).join(""))); break; + case 'base64': fdata = s2a(Base64_decode(data.slice(di).join(""))); break; case 'quoted-printable': fdata = parse_quoted_printable(data.slice(di)); break; default: throw new Error("Unsupported Content-Transfer-Encoding " + cte); }