From ab962d782e810627130cd2a475cb15061ece5d9c Mon Sep 17 00:00:00 2001 From: SheetJS Date: Tue, 20 May 2014 10:43:03 -0700 Subject: [PATCH] version bump 0.9.1: massive cleanup - no pollution of the Array prototype - alignment with js-xls CFB code - removed main code in CFB (use cfb bin instead) - more tests - added dist - correect for incorrect tree level pointers --- LICENSE | 2 +- Makefile | 43 ++-- README.md | 2 + bin/cfb | 4 +- bits/00_header.js | 2 +- bits/08_blob.js | 78 +++----- bits/31_version.js | 1 + bits/42_cfbheader.js | 2 - bits/43_readfat.js | 11 +- bits/44_readdir.js | 6 +- bits/45_rbtree.js | 18 +- bits/90_utils.js | 1 - bits/98_exports.js | 16 +- cfb.js | 135 ++++++------- dist/LICENSE | 13 ++ dist/cfb.js | 454 +++++++++++++++++++++++++++++++++++++++++++ dist/cfb.min.js | 3 + dist/cfb.min.map | 1 + fails.lst | 3 + index.html | 59 ++++++ package.json | 7 +- test.js | 32 ++- 22 files changed, 717 insertions(+), 176 deletions(-) create mode 100644 bits/31_version.js create mode 100644 dist/LICENSE create mode 100644 dist/cfb.js create mode 100644 dist/cfb.min.js create mode 100644 dist/cfb.min.map create mode 100644 fails.lst create mode 100644 index.html diff --git a/LICENSE b/LICENSE index 0275eb7..6d41660 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2013 SheetJS +Copyright (C) 2013-2014 SheetJS Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/Makefile b/Makefile index e92afb3..4e3f7d8 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,42 @@ +LIB=cfb DEPS=$(wildcard bits/*.js) -TARGET=cfb.js +TARGET=$(LIB).js $(TARGET): $(DEPS) cat $^ > $@ -.PHONY: test mocha -test mocha: init - mocha -R spec +bits/31_version.js: package.json + echo "this.version = '"`grep version package.json | awk '{gsub(/[^0-9a-z\.-]/,"",$$2); print $$2}'`"';" > $@ -.PHONY: lint -lint: - jshint cfb.js +.PHONY: clean +clean: + rm -rf $(TARGET) ./test_files/ .PHONY: init init: - if [ ! -e test_files ]; then git clone https://github.com/SheetJS/test_files; cd test_files; make; fi + if [ ! -e test_files ]; then git clone https://github.com/SheetJS/test_files; fi + cd test_files; git pull; make -.PHONY: clean -clean: - rm -rf $(TARGET) ./test_files/ +.PHONY: test mocha +test mocha: test.js + mocha -R spec + +.PHONY: lint +lint: $(TARGET) + jshint --show-non-errors $(TARGET) + +.PHONY: cov +cov: misc/coverage.html + +misc/coverage.html: $(TARGET) test.js + mocha --require blanket -R html-cov > misc/coverage.html + +.PHONY: coveralls +coveralls: + mocha --require blanket --reporter mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js + +.PHONY: dist +dist: $(TARGET) + cp $(TARGET) dist/ + cp LICENSE dist/ + uglifyjs $(TARGET) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)" diff --git a/README.md b/README.md index 293b6c9..257c6fe 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,5 @@ Writing is not supported. It is in the works, but it has not yet been released. This implementation is covered under Apache 2.0 license. It complies with the [Open Specifications Promise](http://www.microsoft.com/openspecifications/) +[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/88c2e1fd637653cd780b3c6d3dcd70ad "githalytics.com")](http://githalytics.com/SheetJS/js-cfb) + diff --git a/bin/cfb b/bin/cfb index 6c6e1e2..3e19d9c 100755 --- a/bin/cfb +++ b/bin/cfb @@ -1,9 +1,9 @@ #!/usr/bin/env node -var CFB = require('../cfb'); +var CFB = require('../'); var fs = require('fs'), program = require('commander'); program - .version('0.8.1') + .version(CFB.version) .usage('[options] ') .option('-q, --quiet', 'print but do not extract') .parse(process.argv); diff --git a/bits/00_header.js b/bits/00_header.js index 442b5bd..076f3cd 100644 --- a/bits/00_header.js +++ b/bits/00_header.js @@ -1,4 +1,4 @@ -/* cfb.js (C) 2013 SheetJS -- http://sheetjs.com */ +/* cfb.js (C) 2013-2014 SheetJS -- http://sheetjs.com */ /* vim: set ts=2: */ /*jshint eqnull:true */ diff --git a/bits/08_blob.js b/bits/08_blob.js index 67eced7..ef05d9c 100644 --- a/bits/08_blob.js +++ b/bits/08_blob.js @@ -1,26 +1,7 @@ -/** Helper Functions */ -function readIEEE754(buf, idx, isLE, nl, ml) { - if(isLE === undefined) isLE = true; - if(!nl) nl = 8; - if(!ml && nl === 8) ml = 52; - var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1; - var bits = -7, d = isLE ? -1 : 1, i = isLE ? (nl - 1) : 0, s = buf[idx + i]; - - i += d; - e = s & ((1 << (-bits)) - 1); s >>>= (-bits); bits += el; - for (; bits > 0; e = e * 256 + buf[idx + i], i += d, bits -= 8); - m = e & ((1 << (-bits)) - 1); e >>>= (-bits); bits += ml; - for (; bits > 0; m = m * 256 + buf[idx + i], i += d, bits -= 8); - if (e === eMax) return m ? NaN : ((s ? -1 : 1) * Infinity); - else if (e === 0) e = 1 - eBias; - else { m = m + Math.pow(2, ml); e = e - eBias; } - return (s ? -1 : 1) * m * Math.pow(2, e - ml); -} - var Base64 = (function(){ var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; return { - encode: function(input, utf8) { + /* (will need this for writing) encode: function(input, utf8) { var o = ""; var c1, c2, c3, e1, e2, e3, e4; for(var i = 0; i < input.length; ) { @@ -36,7 +17,7 @@ var Base64 = (function(){ o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4); } return o; - }, + },*/ decode: function(input, utf8) { var o = ""; var c1, c2, c3; @@ -65,63 +46,64 @@ function s2a(s) { return w; } +var __toBuffer; if(typeof Buffer !== "undefined") { Buffer.prototype.hexlify= function() { return this.toString('hex'); }; Buffer.prototype.utf16le= function(s,e){return this.toString('utf16le',s,e).replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!');}; Buffer.prototype.utf8 = function(s,e) { return this.toString('utf8',s,e); }; + __toBuffer = function(bufs) { return Buffer.concat(bufs[0]); }; +} else { + __toBuffer = function(bufs) { + var x = []; + for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); } + return x; + }; } -Array.prototype.readUInt8 = function(idx) { return this[idx]; }; -Array.prototype.readUInt16LE = function(idx) { return this[idx+1]*(1<<8)+this[idx]; }; -Array.prototype.readInt16LE = function(idx) { var u = this.readUInt16LE(idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; }; -Array.prototype.readUInt32LE = function(idx) { return this[idx+3]*(1<<24)+this[idx+2]*(1<<16)+this[idx+1]*(1<<8)+this[idx]; }; -Array.prototype.readDoubleLE = function(idx) { return readIEEE754(this, idx||0);}; +var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; }; +var __readUInt16LE = function(b, idx) { return b.readUInt16LE ? b.readUInt16LE(idx) : b[idx+1]*(1<<8)+b[idx]; }; +var __readInt16LE = function(b, idx) { var u = __readUInt16LE(b,idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; }; +var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(idx) : b[idx+3]*(1<<24)+b[idx+2]*(1<<16)+b[idx+1]*(1<<8)+b[idx]; }; +var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; }; -Array.prototype.hexlify = function() { return this.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); }; +var __hexlify = function(b) { return b.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); }; -Array.prototype.utf16le = function(s,e) { var str = ""; for(var i=s; i 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT"; diff --git a/bits/44_readdir.js b/bits/44_readdir.js index 9777dd2..e900a55 100644 --- a/bits/44_readdir.js +++ b/bits/44_readdir.js @@ -9,7 +9,7 @@ function read_directory(idx) { read = ReadShift.bind(blob); var namelen = read(2); if(namelen === 0) return; - var name = blob.utf16le(0,namelen-(Paths.length?2:0)); // OLE + var name = __utf16le(blob,0,namelen-(Paths.length?2:0)); // OLE Paths.push(name); var o = { name: name }; o.type = EntryTypes[read(1)]; @@ -43,12 +43,12 @@ function read_directory(idx) { } if(o.ctime) { var ct = blob.slice(blob.l-24, blob.l-16); - var c2 = (ct.readUInt32LE(4)/1e7)*Math.pow(2,32)+ct.readUInt32LE(0)/1e7; + var c2 = (__readUInt32LE(ct,4)/1e7)*Math.pow(2,32)+__readUInt32LE(ct,0)/1e7; o.ct = new Date((c2 - 11644473600)*1000); } if(o.mtime) { var mt = blob.slice(blob.l-16, blob.l-8); - var m2 = (mt.readUInt32LE(4)/1e7)*Math.pow(2,32)+mt.readUInt32LE(0)/1e7; + var m2 = (__readUInt32LE(mt,4)/1e7)*Math.pow(2,32)+__readUInt32LE(mt,0)/1e7; o.mt = new Date((m2 - 11644473600)*1000); } files[name] = o; diff --git a/bits/45_rbtree.js b/bits/45_rbtree.js index 068297c..0fc7b65 100644 --- a/bits/45_rbtree.js +++ b/bits/45_rbtree.js @@ -7,10 +7,20 @@ function build_full_paths(Dir, pathobj, paths, patharr) { for(i=0; i != dad.length; ++i) { dad[i]=q[i]=i; paths[i]=patharr[i]; } - for(i = q[0]; typeof i !== "undefined"; i = q.shift()) { - if(Dir[i].child) dad[Dir[i].child] = i; - if(Dir[i].left) { dad[Dir[i].left] = dad[i]; q.push(Dir[i].left); } - if(Dir[i].right) { dad[Dir[i].right] = dad[i]; q.push(Dir[i].right); } + while(q.length > 0) { + for(i = q[0]; typeof i !== "undefined"; i = q.shift()) { + if(dad[i] === i) { + if(Dir[i].left && dad[Dir[i].left] != Dir[i].left) dad[i] = dad[Dir[i].left]; + if(Dir[i].right && dad[Dir[i].right] != Dir[i].right) dad[i] = dad[Dir[i].right]; + } + if(Dir[i].child) dad[Dir[i].child] = i; + if(Dir[i].left) { dad[Dir[i].left] = dad[i]; q.push(Dir[i].left); } + if(Dir[i].right) { dad[Dir[i].right] = dad[i]; q.push(Dir[i].right); } + } + for(i=1; i != dad.length; ++i) if(dad[i] === i) { + if(Dir[i].right && dad[Dir[i].right] != Dir[i].right) dad[i] = dad[Dir[i].right]; + else if(Dir[i].left && dad[Dir[i].left] != Dir[i].left) dad[i] = dad[Dir[i].left]; + } } for(i=1; i !== paths.length; ++i) { diff --git a/bits/90_utils.js b/bits/90_utils.js index c4c9d62..b79dde8 100644 --- a/bits/90_utils.js +++ b/bits/90_utils.js @@ -1,6 +1,5 @@ var CFB_utils = { ReadShift: ReadShift, - WarnField: WarnField, CheckField: CheckField, prep_blob: prep_blob, bconcat: bconcat diff --git a/bits/98_exports.js b/bits/98_exports.js index 0cbb33d..e9b7ed0 100644 --- a/bits/98_exports.js +++ b/bits/98_exports.js @@ -1,21 +1,7 @@ if(typeof require !== 'undefined' && typeof exports !== 'undefined') { - Array.prototype.toBuffer = function() { - return Buffer.concat(this[0]); - }; var fs = require('fs'); exports.read = CFB.read; exports.parse = CFB.parse; exports.utils = CFB_utils; - exports.main = function(args) { - var cfb = CFB.read(args[0], {type:'file'}); - console.log(cfb); - }; - if(typeof module !== 'undefined' && require.main === module) - exports.main(process.argv.slice(2)); -} else { - Array.prototype.toBuffer = function() { - var x = []; - for(var i = 0; i != this[0].length; ++i) { x = x.concat(this[0][i]); } - return x; - }; + exports.version = CFB.version; } diff --git a/cfb.js b/cfb.js index 67a34d8..f3bbf5a 100644 --- a/cfb.js +++ b/cfb.js @@ -1,30 +1,11 @@ -/* cfb.js (C) 2013 SheetJS -- http://sheetjs.com */ +/* cfb.js (C) 2013-2014 SheetJS -- http://sheetjs.com */ /* vim: set ts=2: */ /*jshint eqnull:true */ -/** Helper Functions */ -function readIEEE754(buf, idx, isLE, nl, ml) { - if(isLE === undefined) isLE = true; - if(!nl) nl = 8; - if(!ml && nl === 8) ml = 52; - var e, m, el = nl * 8 - ml - 1, eMax = (1 << el) - 1, eBias = eMax >> 1; - var bits = -7, d = isLE ? -1 : 1, i = isLE ? (nl - 1) : 0, s = buf[idx + i]; - - i += d; - e = s & ((1 << (-bits)) - 1); s >>>= (-bits); bits += el; - for (; bits > 0; e = e * 256 + buf[idx + i], i += d, bits -= 8); - m = e & ((1 << (-bits)) - 1); e >>>= (-bits); bits += ml; - for (; bits > 0; m = m * 256 + buf[idx + i], i += d, bits -= 8); - if (e === eMax) return m ? NaN : ((s ? -1 : 1) * Infinity); - else if (e === 0) e = 1 - eBias; - else { m = m + Math.pow(2, ml); e = e - eBias; } - return (s ? -1 : 1) * m * Math.pow(2, e - ml); -} - var Base64 = (function(){ var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; return { - encode: function(input, utf8) { + /* (will need this for writing) encode: function(input, utf8) { var o = ""; var c1, c2, c3, e1, e2, e3, e4; for(var i = 0; i < input.length; ) { @@ -40,7 +21,7 @@ var Base64 = (function(){ o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4); } return o; - }, + },*/ decode: function(input, utf8) { var o = ""; var c1, c2, c3; @@ -69,63 +50,64 @@ function s2a(s) { return w; } +var __toBuffer; if(typeof Buffer !== "undefined") { Buffer.prototype.hexlify= function() { return this.toString('hex'); }; Buffer.prototype.utf16le= function(s,e){return this.toString('utf16le',s,e).replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!');}; Buffer.prototype.utf8 = function(s,e) { return this.toString('utf8',s,e); }; + __toBuffer = function(bufs) { return Buffer.concat(bufs[0]); }; +} else { + __toBuffer = function(bufs) { + var x = []; + for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); } + return x; + }; } -Array.prototype.readUInt8 = function(idx) { return this[idx]; }; -Array.prototype.readUInt16LE = function(idx) { return this[idx+1]*(1<<8)+this[idx]; }; -Array.prototype.readInt16LE = function(idx) { var u = this.readUInt16LE(idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; }; -Array.prototype.readUInt32LE = function(idx) { return this[idx+3]*(1<<24)+this[idx+2]*(1<<16)+this[idx+1]*(1<<8)+this[idx]; }; -Array.prototype.readDoubleLE = function(idx) { return readIEEE754(this, idx||0);}; +var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; }; +var __readUInt16LE = function(b, idx) { return b.readUInt16LE ? b.readUInt16LE(idx) : b[idx+1]*(1<<8)+b[idx]; }; +var __readInt16LE = function(b, idx) { var u = __readUInt16LE(b,idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; }; +var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(idx) : b[idx+3]*(1<<24)+b[idx+2]*(1<<16)+b[idx+1]*(1<<8)+b[idx]; }; +var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; }; -Array.prototype.hexlify = function() { return this.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); }; +var __hexlify = function(b) { return b.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); }; -Array.prototype.utf16le = function(s,e) { var str = ""; for(var i=s; i 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT"; @@ -303,7 +283,7 @@ function read_directory(idx) { read = ReadShift.bind(blob); var namelen = read(2); if(namelen === 0) return; - var name = blob.utf16le(0,namelen-(Paths.length?2:0)); // OLE + var name = __utf16le(blob,0,namelen-(Paths.length?2:0)); // OLE Paths.push(name); var o = { name: name }; o.type = EntryTypes[read(1)]; @@ -337,12 +317,12 @@ function read_directory(idx) { } if(o.ctime) { var ct = blob.slice(blob.l-24, blob.l-16); - var c2 = (ct.readUInt32LE(4)/1e7)*Math.pow(2,32)+ct.readUInt32LE(0)/1e7; + var c2 = (__readUInt32LE(ct,4)/1e7)*Math.pow(2,32)+__readUInt32LE(ct,0)/1e7; o.ct = new Date((c2 - 11644473600)*1000); } if(o.mtime) { var mt = blob.slice(blob.l-16, blob.l-8); - var m2 = (mt.readUInt32LE(4)/1e7)*Math.pow(2,32)+mt.readUInt32LE(0)/1e7; + var m2 = (__readUInt32LE(mt,4)/1e7)*Math.pow(2,32)+__readUInt32LE(mt,0)/1e7; o.mt = new Date((m2 - 11644473600)*1000); } files[name] = o; @@ -360,10 +340,20 @@ function build_full_paths(Dir, pathobj, paths, patharr) { for(i=0; i != dad.length; ++i) { dad[i]=q[i]=i; paths[i]=patharr[i]; } - for(i = q[0]; typeof i !== "undefined"; i = q.shift()) { - if(Dir[i].child) dad[Dir[i].child] = i; - if(Dir[i].left) { dad[Dir[i].left] = dad[i]; q.push(Dir[i].left); } - if(Dir[i].right) { dad[Dir[i].right] = dad[i]; q.push(Dir[i].right); } + while(q.length > 0) { + for(i = q[0]; typeof i !== "undefined"; i = q.shift()) { + if(dad[i] === i) { + if(Dir[i].left && dad[Dir[i].left] != Dir[i].left) dad[i] = dad[Dir[i].left]; + if(Dir[i].right && dad[Dir[i].right] != Dir[i].right) dad[i] = dad[Dir[i].right]; + } + if(Dir[i].child) dad[Dir[i].child] = i; + if(Dir[i].left) { dad[Dir[i].left] = dad[i]; q.push(Dir[i].left); } + if(Dir[i].right) { dad[Dir[i].right] = dad[i]; q.push(Dir[i].right); } + } + for(i=1; i != dad.length; ++i) if(dad[i] === i) { + if(Dir[i].right && dad[Dir[i].right] != Dir[i].right) dad[i] = dad[Dir[i].right]; + else if(Dir[i].left && dad[Dir[i].left] != Dir[i].left) dad[i] = dad[Dir[i].left]; + } } for(i=1; i !== paths.length; ++i) { @@ -450,30 +440,15 @@ return this; var CFB_utils = { ReadShift: ReadShift, - WarnField: WarnField, CheckField: CheckField, prep_blob: prep_blob, bconcat: bconcat }; if(typeof require !== 'undefined' && typeof exports !== 'undefined') { - Array.prototype.toBuffer = function() { - return Buffer.concat(this[0]); - }; var fs = require('fs'); exports.read = CFB.read; exports.parse = CFB.parse; exports.utils = CFB_utils; - exports.main = function(args) { - var cfb = CFB.read(args[0], {type:'file'}); - console.log(cfb); - }; - if(typeof module !== 'undefined' && require.main === module) - exports.main(process.argv.slice(2)); -} else { - Array.prototype.toBuffer = function() { - var x = []; - for(var i = 0; i != this[0].length; ++i) { x = x.concat(this[0][i]); } - return x; - }; + exports.version = CFB.version; } diff --git a/dist/LICENSE b/dist/LICENSE new file mode 100644 index 0000000..6d41660 --- /dev/null +++ b/dist/LICENSE @@ -0,0 +1,13 @@ +Copyright (C) 2013-2014 SheetJS + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/dist/cfb.js b/dist/cfb.js new file mode 100644 index 0000000..f3bbf5a --- /dev/null +++ b/dist/cfb.js @@ -0,0 +1,454 @@ +/* cfb.js (C) 2013-2014 SheetJS -- http://sheetjs.com */ +/* vim: set ts=2: */ +/*jshint eqnull:true */ + +var Base64 = (function(){ + var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + return { + /* (will need this for writing) encode: function(input, utf8) { + var o = ""; + var c1, c2, c3, e1, e2, e3, e4; + for(var i = 0; i < input.length; ) { + c1 = input.charCodeAt(i++); + c2 = input.charCodeAt(i++); + c3 = input.charCodeAt(i++); + e1 = c1 >> 2; + e2 = (c1 & 3) << 4 | c2 >> 4; + 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(input, utf8) { + var o = ""; + var c1, c2, c3; + var e1, e2, e3, e4; + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + for(var i = 0; i < input.length;) { + e1 = map.indexOf(input.charAt(i++)); + e2 = map.indexOf(input.charAt(i++)); + e3 = map.indexOf(input.charAt(i++)); + e4 = map.indexOf(input.charAt(i++)); + c1 = e1 << 2 | e2 >> 4; + c2 = (e2 & 15) << 4 | e3 >> 2; + c3 = (e3 & 3) << 6 | e4; + o += String.fromCharCode(c1); + if (e3 != 64) { o += String.fromCharCode(c2); } + if (e4 != 64) { o += String.fromCharCode(c3); } + } + return o; + } + }; +})(); + +function s2a(s) { + if(typeof Buffer !== 'undefined') return new Buffer(s, "binary"); + var w = s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); + return w; +} + +var __toBuffer; +if(typeof Buffer !== "undefined") { + Buffer.prototype.hexlify= function() { return this.toString('hex'); }; + Buffer.prototype.utf16le= function(s,e){return this.toString('utf16le',s,e).replace(/\u0000/,'').replace(/[\u0001-\u0006]/,'!');}; + Buffer.prototype.utf8 = function(s,e) { return this.toString('utf8',s,e); }; + __toBuffer = function(bufs) { return Buffer.concat(bufs[0]); }; +} else { + __toBuffer = function(bufs) { + var x = []; + for(var i = 0; i != bufs[0].length; ++i) { x = x.concat(bufs[0][i]); } + return x; + }; +} + +var __readUInt8 = function(b, idx) { return b.readUInt8 ? b.readUInt8(idx) : b[idx]; }; +var __readUInt16LE = function(b, idx) { return b.readUInt16LE ? b.readUInt16LE(idx) : b[idx+1]*(1<<8)+b[idx]; }; +var __readInt16LE = function(b, idx) { var u = __readUInt16LE(b,idx); if(!(u & 0x8000)) return u; return (0xffff - u + 1) * -1; }; +var __readUInt32LE = function(b, idx) { return b.readUInt32LE ? b.readUInt32LE(idx) : b[idx+3]*(1<<24)+b[idx+2]*(1<<16)+b[idx+1]*(1<<8)+b[idx]; }; +var __readInt32LE = function(b, idx) { if(b.readInt32LE) return b.readInt32LE(idx); var u = __readUInt32LE(b,idx); if(!(u & 0x80000000)) return u; return (0xffffffff - u + 1) * -1; }; + +var __hexlify = function(b) { return b.map(function(x){return (x<16?"0":"") + x.toString(16);}).join(""); }; + +var __utf16le = function(b,s,e) { if(b.utf16le) return b.utf16le(s,e); var ss=[]; for(var i=s; i=MAXREGSECT) break; + fat_addrs[j++] = q; +} + + +/** Break the file up into sectors */ +var nsectors = Math.ceil((file.length - ssz)/ssz); +var sectors = []; +for(var i=1; i != nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz); +sectors[nsectors-1] = file.slice(nsectors*ssz); + +/** Chase down the rest of the DIFAT chain to build a comprehensive list + DIFAT chains by storing the next sector number as the last 32 bytes */ +function sleuth_fat(idx, cnt) { + if(idx === ENDOFCHAIN) { + if(cnt !== 0) throw "DIFAT chain shorter than expected"; + return; + } + if(idx !== FREESECT) { + var sector = sectors[idx]; + for(var i = 0; i != ssz/4-1; ++i) { + if((q = __readUInt32LE(sector,i*4)) === ENDOFCHAIN) break; + fat_addrs.push(q); + } + sleuth_fat(__readUInt32LE(sector,ssz-4),cnt - 1); + } +} +sleuth_fat(difat_start, ndfs); + +/** DONT CAT THE FAT! Just calculate where we need to go */ +function get_buffer(byte_addr, bytes) { + var addr = fat_addrs[Math.floor(byte_addr*4/ssz)]; + if(ssz - (byte_addr*4 % ssz) < (bytes || 0)) throw "FAT boundary crossed: " + byte_addr + " "+bytes+" "+ssz; + return sectors[addr].slice((byte_addr*4 % ssz)); +} + +function get_buffer_u32(byte_addr) { + return __readUInt32LE(get_buffer(byte_addr,4), 0); +} + +function get_next_sector(idx) { return get_buffer_u32(idx); } + +/** Chains */ +var chkd = new Array(sectors.length), sector_list = []; +var get_sector = function get_sector(k) { return sectors[k]; }; +for(i=0; i != sectors.length; ++i) { + var buf = [], k = (i + dir_start) % sectors.length; + if(chkd[k]) continue; + for(j=k; j<=MAXREGSECT; buf.push(j),j=get_next_sector(j)) chkd[j] = true; + sector_list[k] = {nodes: buf}; + sector_list[k].data = __toBuffer(Array(buf.map(get_sector))); +} +sector_list[dir_start].name = "!Directory"; +if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT"; +sector_list[fat_addrs[0]].name = "!FAT"; + +/* [MS-CFB] 2.6.1 Compound File Directory Entry */ +var files = {}, Paths = [], FileIndex = [], FullPaths = [], FullPathDir = {}; +function read_directory(idx) { + var blob, read, w; + var sector = sector_list[idx].data; + for(var i = 0; i != sector.length; i+= 128) { + blob = sector.slice(i, i+128); + prep_blob(blob, 64); + read = ReadShift.bind(blob); + var namelen = read(2); + if(namelen === 0) return; + var name = __utf16le(blob,0,namelen-(Paths.length?2:0)); // OLE + Paths.push(name); + var o = { name: name }; + o.type = EntryTypes[read(1)]; + o.color = read(1); + o.left = read(4); if(o.left === NOSTREAM) delete o.left; + o.right = read(4); if(o.right === NOSTREAM) delete o.right; + o.child = read(4); if(o.child === NOSTREAM) delete o.child; + o.clsid = read(16); + o.state = read(4); + var ctime = read(8); if(ctime != "0000000000000000") o.ctime = ctime; + var mtime = read(8); if(mtime != "0000000000000000") o.mtime = mtime; + o.start = read(4); + o.size = read(4); + if(o.type === 'root') { //root entry + minifat_store = o.start; + if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData"; + minifat_size = o.size; + } else if(o.size >= ms_cutoff_size) { + o.storage = 'fat'; + if(!sector_list[o.start] && dir_start > 0) o.start = (o.start + dir_start) % sectors.length; + sector_list[o.start].name = o.name; + o.content = sector_list[o.start].data.slice(0,o.size); + prep_blob(o.content); + } else { + o.storage = 'minifat'; + w = o.start * mssz; + if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { + o.content = sector_list[minifat_store].data.slice(w,w+o.size); + prep_blob(o.content); + } + } + if(o.ctime) { + var ct = blob.slice(blob.l-24, blob.l-16); + var c2 = (__readUInt32LE(ct,4)/1e7)*Math.pow(2,32)+__readUInt32LE(ct,0)/1e7; + o.ct = new Date((c2 - 11644473600)*1000); + } + if(o.mtime) { + var mt = blob.slice(blob.l-16, blob.l-8); + var m2 = (__readUInt32LE(mt,4)/1e7)*Math.pow(2,32)+__readUInt32LE(mt,0)/1e7; + o.mt = new Date((m2 - 11644473600)*1000); + } + files[name] = o; + FileIndex.push(o); + } +} +read_directory(dir_start); + +/* [MS-CFB] 2.6.4 Red-Black Tree */ +function build_full_paths(Dir, pathobj, paths, patharr) { + var i; + var dad = new Array(patharr.length); + + var q = new Array(patharr.length); + + for(i=0; i != dad.length; ++i) { dad[i]=q[i]=i; paths[i]=patharr[i]; } + + while(q.length > 0) { + for(i = q[0]; typeof i !== "undefined"; i = q.shift()) { + if(dad[i] === i) { + if(Dir[i].left && dad[Dir[i].left] != Dir[i].left) dad[i] = dad[Dir[i].left]; + if(Dir[i].right && dad[Dir[i].right] != Dir[i].right) dad[i] = dad[Dir[i].right]; + } + if(Dir[i].child) dad[Dir[i].child] = i; + if(Dir[i].left) { dad[Dir[i].left] = dad[i]; q.push(Dir[i].left); } + if(Dir[i].right) { dad[Dir[i].right] = dad[i]; q.push(Dir[i].right); } + } + for(i=1; i != dad.length; ++i) if(dad[i] === i) { + if(Dir[i].right && dad[Dir[i].right] != Dir[i].right) dad[i] = dad[Dir[i].right]; + else if(Dir[i].left && dad[Dir[i].left] != Dir[i].left) dad[i] = dad[Dir[i].left]; + } + } + + for(i=1; i !== paths.length; ++i) { + if(Dir[i].type === "unknown") continue; + var j = dad[i]; + if(j === 0) paths[i] = paths[0] + "/" + paths[i]; + else while(j !== 0) { + paths[i] = paths[j] + "/" + paths[i]; + j = dad[j]; + } + dad[i] = 0; + } + + paths[0] += "/"; + for(i=1; i !== paths.length; ++i) if(Dir[i].type !== 'stream') paths[i] += "/"; + for(i=0; i !== paths.length; ++i) pathobj[paths[i]] = FileIndex[i]; +} +build_full_paths(FileIndex, FullPathDir, FullPaths, Paths); + +var root_name = Paths.shift(); +Paths.root = root_name; + +/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ +function find_path(path) { + if(path[0] === "/") path = root_name + path; + var UCNames = (path.indexOf("/") !== -1 ? FullPaths : Paths).map(function(x) { return x.toUpperCase(); }); + var UCPath = path.toUpperCase(); + var w = UCNames.indexOf(UCPath); + if(w === -1) return null; + return path.indexOf("/") !== -1 ? FileIndex[w] : files[Paths[w]]; +} + +var rval = { + raw: {header: header, sectors: sectors}, + FileIndex: FileIndex, + FullPaths: FullPaths, + FullPathDir: FullPathDir, + find: find_path +}; + +return rval; +} // parse + + +function readFileSync(filename) { + var fs = require('fs'); + var file = fs.readFileSync(filename); + return parse(file); +} + +function readSync(blob, options) { + var o = options || {}; + switch((o.type || "base64")) { + case "file": return readFileSync(blob); + case "base64": blob = Base64.decode(blob); + /* falls through */ + case "binary": blob = s2a(blob); break; + } + return parse(blob); +} + +this.read = readSync; +this.parse = parse; +return this; +})(); + +/** CFB Constants */ +{ + /* 2.1 Compund File Sector Numbers and Types */ + var MAXREGSECT = 0xFFFFFFFA; + var DIFSECT = 0xFFFFFFFC; + var FATSECT = 0xFFFFFFFD; + var ENDOFCHAIN = 0xFFFFFFFE; + var FREESECT = 0xFFFFFFFF; + /* 2.2 Compound File Header */ + var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1'; + var HEADER_MINOR_VERSION = '3e00'; + var MAXREGSID = 0xFFFFFFFA; + var NOSTREAM = 0xFFFFFFFF; + var HEADER_CLSID = '00000000000000000000000000000000'; + /* 2.6.1 Compound File Directory Entry */ + var EntryTypes = ['unknown','storage','stream','lockbytes','property','root']; +} + +var CFB_utils = { + ReadShift: ReadShift, + CheckField: CheckField, + prep_blob: prep_blob, + bconcat: bconcat +}; + +if(typeof require !== 'undefined' && typeof exports !== 'undefined') { + var fs = require('fs'); + exports.read = CFB.read; + exports.parse = CFB.parse; + exports.utils = CFB_utils; + exports.version = CFB.version; +} diff --git a/dist/cfb.min.js b/dist/cfb.min.js new file mode 100644 index 0000000..7318b85 --- /dev/null +++ b/dist/cfb.min.js @@ -0,0 +1,3 @@ +/* cfb.js (C) 2013-2014 SheetJS -- http://sheetjs.com */ +var Base64=function(){var map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{decode:function(input,utf8){var o="";var c1,c2,c3;var e1,e2,e3,e4;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");for(var i=0;i>4;c2=(e2&15)<<4|e3>>2;c3=(e3&3)<<6|e4;o+=String.fromCharCode(c1);if(e3!=64){o+=String.fromCharCode(c2)}if(e4!=64){o+=String.fromCharCode(c3)}}return o}}}();function s2a(s){if(typeof Buffer!=="undefined")return new Buffer(s,"binary");var w=s.split("").map(function(x){return x.charCodeAt(0)&255});return w}var __toBuffer;if(typeof Buffer!=="undefined"){Buffer.prototype.hexlify=function(){return this.toString("hex")};Buffer.prototype.utf16le=function(s,e){return this.toString("utf16le",s,e).replace(/\u0000/,"").replace(/[\u0001-\u0006]/,"!")};Buffer.prototype.utf8=function(s,e){return this.toString("utf8",s,e)};__toBuffer=function(bufs){return Buffer.concat(bufs[0])}}else{__toBuffer=function(bufs){var x=[];for(var i=0;i!=bufs[0].length;++i){x=x.concat(bufs[0][i])}return x}}var __readUInt8=function(b,idx){return b.readUInt8?b.readUInt8(idx):b[idx]};var __readUInt16LE=function(b,idx){return b.readUInt16LE?b.readUInt16LE(idx):b[idx+1]*(1<<8)+b[idx]};var __readInt16LE=function(b,idx){var u=__readUInt16LE(b,idx);if(!(u&32768))return u;return(65535-u+1)*-1};var __readUInt32LE=function(b,idx){return b.readUInt32LE?b.readUInt32LE(idx):b[idx+3]*(1<<24)+b[idx+2]*(1<<16)+b[idx+1]*(1<<8)+b[idx]};var __readInt32LE=function(b,idx){if(b.readInt32LE)return b.readInt32LE(idx);var u=__readUInt32LE(b,idx);if(!(u&2147483648))return u;return(4294967295-u+1)*-1};var __hexlify=function(b){return b.map(function(x){return(x<16?"0":"")+x.toString(16)}).join("")};var __utf16le=function(b,s,e){if(b.utf16le)return b.utf16le(s,e);var ss=[];for(var i=s;i=MAXREGSECT)break;fat_addrs[j++]=q}var nsectors=Math.ceil((file.length-ssz)/ssz);var sectors=[];for(var i=1;i!=nsectors;++i)sectors[i-1]=file.slice(i*ssz,(i+1)*ssz);sectors[nsectors-1]=file.slice(nsectors*ssz);function sleuth_fat(idx,cnt){if(idx===ENDOFCHAIN){if(cnt!==0)throw"DIFAT chain shorter than expected";return}if(idx!==FREESECT){var sector=sectors[idx];for(var i=0;i!=ssz/4-1;++i){if((q=__readUInt32LE(sector,i*4))===ENDOFCHAIN)break;fat_addrs.push(q)}sleuth_fat(__readUInt32LE(sector,ssz-4),cnt-1)}}sleuth_fat(difat_start,ndfs);function get_buffer(byte_addr,bytes){var addr=fat_addrs[Math.floor(byte_addr*4/ssz)];if(ssz-byte_addr*4%ssz<(bytes||0))throw"FAT boundary crossed: "+byte_addr+" "+bytes+" "+ssz;return sectors[addr].slice(byte_addr*4%ssz)}function get_buffer_u32(byte_addr){return __readUInt32LE(get_buffer(byte_addr,4),0)}function get_next_sector(idx){return get_buffer_u32(idx)}var chkd=new Array(sectors.length),sector_list=[];var get_sector=function get_sector(k){return sectors[k]};for(i=0;i!=sectors.length;++i){var buf=[],k=(i+dir_start)%sectors.length;if(chkd[k])continue;for(j=k;j<=MAXREGSECT;buf.push(j),j=get_next_sector(j))chkd[j]=true;sector_list[k]={nodes:buf};sector_list[k].data=__toBuffer(Array(buf.map(get_sector)))}sector_list[dir_start].name="!Directory";if(nmfs>0&&minifat_start!==ENDOFCHAIN)sector_list[minifat_start].name="!MiniFAT";sector_list[fat_addrs[0]].name="!FAT";var files={},Paths=[],FileIndex=[],FullPaths=[],FullPathDir={};function read_directory(idx){var blob,read,w;var sector=sector_list[idx].data;for(var i=0;i!=sector.length;i+=128){blob=sector.slice(i,i+128);prep_blob(blob,64);read=ReadShift.bind(blob);var namelen=read(2);if(namelen===0)return;var name=__utf16le(blob,0,namelen-(Paths.length?2:0));Paths.push(name);var o={name:name};o.type=EntryTypes[read(1)];o.color=read(1);o.left=read(4);if(o.left===NOSTREAM)delete o.left;o.right=read(4);if(o.right===NOSTREAM)delete o.right;o.child=read(4);if(o.child===NOSTREAM)delete o.child;o.clsid=read(16);o.state=read(4);var ctime=read(8);if(ctime!="0000000000000000")o.ctime=ctime;var mtime=read(8);if(mtime!="0000000000000000")o.mtime=mtime;o.start=read(4);o.size=read(4);if(o.type==="root"){minifat_store=o.start;if(nmfs>0&&minifat_store!==ENDOFCHAIN)sector_list[minifat_store].name="!StreamData";minifat_size=o.size}else if(o.size>=ms_cutoff_size){o.storage="fat";if(!sector_list[o.start]&&dir_start>0)o.start=(o.start+dir_start)%sectors.length;sector_list[o.start].name=o.name;o.content=sector_list[o.start].data.slice(0,o.size);prep_blob(o.content)}else{o.storage="minifat";w=o.start*mssz;if(minifat_store!==ENDOFCHAIN&&o.start!==ENDOFCHAIN){o.content=sector_list[minifat_store].data.slice(w,w+o.size);prep_blob(o.content)}}if(o.ctime){var ct=blob.slice(blob.l-24,blob.l-16);var c2=__readUInt32LE(ct,4)/1e7*Math.pow(2,32)+__readUInt32LE(ct,0)/1e7;o.ct=new Date((c2-11644473600)*1e3)}if(o.mtime){var mt=blob.slice(blob.l-16,blob.l-8);var m2=__readUInt32LE(mt,4)/1e7*Math.pow(2,32)+__readUInt32LE(mt,0)/1e7;o.mt=new Date((m2-11644473600)*1e3)}files[name]=o;FileIndex.push(o)}}read_directory(dir_start);function build_full_paths(Dir,pathobj,paths,patharr){var i;var dad=new Array(patharr.length);var q=new Array(patharr.length);for(i=0;i!=dad.length;++i){dad[i]=q[i]=i;paths[i]=patharr[i]}while(q.length>0){for(i=q[0];typeof i!=="undefined";i=q.shift()){if(dad[i]===i){if(Dir[i].left&&dad[Dir[i].left]!=Dir[i].left)dad[i]=dad[Dir[i].left];if(Dir[i].right&&dad[Dir[i].right]!=Dir[i].right)dad[i]=dad[Dir[i].right]}if(Dir[i].child)dad[Dir[i].child]=i;if(Dir[i].left){dad[Dir[i].left]=dad[i];q.push(Dir[i].left)}if(Dir[i].right){dad[Dir[i].right]=dad[i];q.push(Dir[i].right)}}for(i=1;i!=dad.length;++i)if(dad[i]===i){if(Dir[i].right&&dad[Dir[i].right]!=Dir[i].right)dad[i]=dad[Dir[i].right];else if(Dir[i].left&&dad[Dir[i].left]!=Dir[i].left)dad[i]=dad[Dir[i].left]}}for(i=1;i!==paths.length;++i){if(Dir[i].type==="unknown")continue;var j=dad[i];if(j===0)paths[i]=paths[0]+"/"+paths[i];else while(j!==0){paths[i]=paths[j]+"/"+paths[i];j=dad[j]}dad[i]=0}paths[0]+="/";for(i=1;i!==paths.length;++i)if(Dir[i].type!=="stream")paths[i]+="/";for(i=0;i!==paths.length;++i)pathobj[paths[i]]=FileIndex[i]}build_full_paths(FileIndex,FullPathDir,FullPaths,Paths);var root_name=Paths.shift();Paths.root=root_name;function find_path(path){if(path[0]==="/")path=root_name+path;var UCNames=(path.indexOf("/")!==-1?FullPaths:Paths).map(function(x){return x.toUpperCase()});var UCPath=path.toUpperCase();var w=UCNames.indexOf(UCPath);if(w===-1)return null;return path.indexOf("/")!==-1?FileIndex[w]:files[Paths[w]]}var rval={raw:{header:header,sectors:sectors},FileIndex:FileIndex,FullPaths:FullPaths,FullPathDir:FullPathDir,find:find_path};return rval}function readFileSync(filename){var fs=require("fs");var file=fs.readFileSync(filename);return parse(file)}function readSync(blob,options){var o=options||{};switch(o.type||"base64"){case"file":return readFileSync(blob);case"base64":blob=Base64.decode(blob);case"binary":blob=s2a(blob);break}return parse(blob)}this.read=readSync;this.parse=parse;return this}();{var MAXREGSECT=4294967290;var DIFSECT=4294967292;var FATSECT=4294967293;var ENDOFCHAIN=4294967294;var FREESECT=4294967295;var HEADER_SIGNATURE="d0cf11e0a1b11ae1";var HEADER_MINOR_VERSION="3e00";var MAXREGSID=4294967290;var NOSTREAM=4294967295;var HEADER_CLSID="00000000000000000000000000000000";var EntryTypes=["unknown","storage","stream","lockbytes","property","root"]}var CFB_utils={ReadShift:ReadShift,CheckField:CheckField,prep_blob:prep_blob,bconcat:bconcat};if(typeof require!=="undefined"&&typeof exports!=="undefined"){var fs=require("fs");exports.read=CFB.read;exports.parse=CFB.parse;exports.utils=CFB_utils;exports.version=CFB.version} +//# sourceMappingURL=dist/cfb.min.map \ No newline at end of file diff --git a/dist/cfb.min.map b/dist/cfb.min.map new file mode 100644 index 0000000..210a0d9 --- /dev/null +++ b/dist/cfb.min.map @@ -0,0 +1 @@ +{"version":3,"file":"dist/cfb.min.js","sources":["cfb.js"],"names":["Base64","map","decode","input","utf8","o","c1","c2","c3","e1","e2","e3","e4","replace","i","length","indexOf","charAt","String","fromCharCode","s2a","s","Buffer","w","split","x","charCodeAt","__toBuffer","prototype","hexlify","this","toString","utf16le","e","bufs","concat","__readUInt8","b","idx","readUInt8","__readUInt16LE","readUInt16LE","__readInt16LE","u","__readUInt32LE","readUInt32LE","__readInt32LE","readInt32LE","__hexlify","join","__utf16le","ss","push","__utf8","bconcat","apply","ReadShift","size","t","oo","vv","l","CheckField","hexstr","fld","slice","m","prep_blob","blob","pos","read_shift","bind","chk","read","CFB","version","parse","file","mver","ssz","mssz","nds","nfs","nmfs","ndfs","dir_start","minifat_start","difat_start","ms_cutoff_size","minifat_store","minifat_size","fat_addrs","j","q","HEADER_SIGNATURE","HEADER_CLSID","header","MAXREGSECT","nsectors","Math","ceil","sectors","sleuth_fat","cnt","ENDOFCHAIN","FREESECT","sector","get_buffer","byte_addr","bytes","addr","floor","get_buffer_u32","get_next_sector","chkd","Array","sector_list","get_sector","k","buf","nodes","data","name","files","Paths","FileIndex","FullPaths","FullPathDir","read_directory","namelen","type","EntryTypes","color","left","NOSTREAM","right","child","clsid","state","ctime","mtime","start","storage","content","ct","pow","Date","mt","m2","build_full_paths","Dir","pathobj","paths","patharr","dad","shift","root_name","root","find_path","path","UCNames","toUpperCase","UCPath","rval","raw","find","readFileSync","filename","fs","require","readSync","options","DIFSECT","FATSECT","HEADER_MINOR_VERSION","MAXREGSID","CFB_utils","exports","utils"],"mappings":"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"} \ No newline at end of file diff --git a/fails.lst b/fails.lst new file mode 100644 index 0000000..db84d98 --- /dev/null +++ b/fails.lst @@ -0,0 +1,3 @@ +roo_type_excelx.xls +roo_type_openoffice.xls +libreoffice_calc_csv-import_malformed-quotes.xls diff --git a/index.html b/index.html new file mode 100644 index 0000000..97af2eb --- /dev/null +++ b/index.html @@ -0,0 +1,59 @@ + + +JS-CFB Live Demo
+ +
Drop an XLS file here to see the CFB structure.
+

+
+ + diff --git a/package.json b/package.json index f5b8652..433bfc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cfb", - "version": "0.8.1", + "version": "0.9.1", "author": "SheetJS", "description": "Compound File Binary File Format extractor", "keywords": [ "cfb", "compression", "office" ], @@ -15,6 +15,11 @@ "dependencies": { "commander":"" }, + "config": { + "blanket": { + "pattern": "cfb.js" + } + }, "bugs": { "url": "https://github.com/SheetJS/js-cfb/issues" }, "license": "Apache 2.0" } diff --git a/test.js b/test.js index d432b26..7bf1b36 100644 --- a/test.js +++ b/test.js @@ -3,7 +3,12 @@ var CFB; var fs = require('fs'); describe('source', function() { it('should load', function() { CFB = require('./'); }); }); -var files = fs.readdirSync('test_files').filter(function(x){return x.substr(-4)==".xls";}); +var fails = fs.existsSync('./fails.lst') ? fs.readFileSync('./fails.lst', 'utf-8').split("\n") : []; +var files = fs.readdirSync('test_files').filter(function(x){return x.substr(-4)==".xls" && fails.indexOf(x) === -1;}); +var f2011 = fs.readdirSync('test_files/2011').filter(function(x){return x.substr(-4)==".xls" && fails.indexOf(x) === -1;}); +var f2013 = fs.readdirSync('test_files/2013').filter(function(x){return x.substr(-4)==".xls" && fails.indexOf(x) === -1;}); + +var dir = "./test_files/"; function parsetest(x, cfb) { describe(x + ' should have basic parts', function() { @@ -14,6 +19,8 @@ function parsetest(x, cfb) { if(!cfb.find('/Workbook') && !cfb.find('/Book')) throw new Error("Cannot find workbook for " + x); }); }); + describe(x + ' should ', function() { + }); } describe('should parse test files', function() { @@ -23,4 +30,27 @@ describe('should parse test files', function() { parsetest(x, cfb); }); }); + f2011.forEach(function(x) { + it('should parse ' + x, function() { + var cfb = CFB.read('./test_files/2011/' + x, {type: "file"}); + parsetest(x, cfb); + }); + }); + f2013.forEach(function(x) { + it('should parse ' + x, function() { + var cfb = CFB.read('./test_files/2013/' + x, {type: "file"}); + parsetest(x, cfb); + }); + }); +}); + +var cp = 'custom_properties.xls' + +describe('input formats', function() { + it('should read binary strings', function() { + CFB.read(fs.readFileSync(dir + '/' + cp, 'binary'), {type: 'binary'}); + }); + it('should read base64 strings', function() { + CFB.read(fs.readFileSync(dir + '/' + cp, 'base64'), {type: 'base64'}); + }); });