From 5a769874f4d2a766142fffa77a901973bbe24474 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Fri, 28 Jul 2017 13:53:08 -0400 Subject: [PATCH] version bump 0.12.0: refresh - pin dependencies - flow and typescript improvements - updated repo infrastructure --- .eslintrc | 18 ++++ Makefile | 21 +++-- README.md | 2 +- bin/cfb.njs | 4 +- bits/08_blob.js | 64 +++++++------ bits/10_types.js | 13 ++- bits/30_cfbheader.js | 2 +- bits/31_version.js | 2 +- bits/40_parse.js | 21 ++--- bits/41_mver.js | 6 +- bits/42_sectorify.js | 4 +- bits/43_rbtree.js | 4 +- bits/44_findpath.js | 14 +-- bits/45_readfat.js | 30 +++--- bits/46_readdir.js | 33 +++---- bits/49_readutils.js | 18 ++-- cfb.flow.js | 211 ++++++++++++++++++++++--------------------- cfb.js | 102 +++++++++++---------- dist/cfb.js | 123 +++++++++++++------------ dist/cfb.min.js | 2 +- dist/cfb.min.map | 2 +- dist/xlscfb.js | 91 +++++++++---------- misc/cfb.d.ts | 104 --------------------- misc/cfb_.ts | 35 ------- misc/flow.js | 86 +++++++++++++++++- misc/node.d.ts | 8 -- package.json | 33 ++++--- types/bin_cfb.ts | 35 +++++++ types/index.d.ts | 100 ++++++++++++++++++++ types/tsconfig.json | 14 +++ types/tslint.json | 11 +++ xlscfb.flow.js | 147 +++++++++++++++--------------- xlscfb.js | 72 +++++++-------- 33 files changed, 782 insertions(+), 650 deletions(-) create mode 100644 .eslintrc delete mode 100644 misc/cfb.d.ts delete mode 100755 misc/cfb_.ts delete mode 100644 misc/node.d.ts create mode 100755 types/bin_cfb.ts create mode 100644 types/index.d.ts create mode 100644 types/tsconfig.json create mode 100644 types/tslint.json diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..3ae0c77 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,18 @@ +{ + "env": { "shared-node-browser":true }, + "globals": {}, + "parserOptions": { + "ecmaVersion": 3, + }, + "plugins": [ "html", "json" ], + "!extends": "eslint:recommended", + "rules": { + "no-console": 0, + "no-bitwise": 0, + "curly": 0, + "comma-style": [ 2, "last" ], + "no-trailing-spaces": 2, + "semi": [ 2, "always" ], + "comma-dangle": [ 2, "never" ] + } +} diff --git a/Makefile b/Makefile index 26ef692..946e096 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ DEPS=$(sort $(wildcard bits/*.js)) TARGET=$(LIB).js FLOWTARGET=$(LIB).flow.js FLOWTGTS=$(TARGET) $(AUXTARGETS) +UGLIFYOPTS=--support-ie8 CLOSURE=/usr/local/lib/node_modules/google-closure-compiler/compiler.jar ## Main Targets @@ -47,7 +48,7 @@ init: ## Initial setup for development dist: dist-deps $(TARGET) ## Prepare JS files for distribution 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)" + uglifyjs $(UGLIFYOPTS) $(TARGET) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)" misc/strip_sourcemap.sh dist/$(LIB).min.js .PHONY: dist-deps @@ -81,7 +82,12 @@ $(TESTFMT): test_%: ## Code Checking .PHONY: lint -lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks +lint: $(TARGET) $(AUXTARGETS) ## Run eslint checks + @eslint --ext .js,.njs,.json,.html,.htm $(TARGET) $(AUXTARGETS) $(CMDS) $(HTMLLINT) package.json + if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi + +.PHONY: old-lint +old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks @jshint --show-non-errors $(TARGET) $(AUXTARGETS) @jshint --show-non-errors $(CMDS) @jshint --show-non-errors package.json @@ -89,6 +95,11 @@ lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks @jscs $(TARGET) $(AUXTARGETS) if [ -e $(CLOSURE) ]; then java -jar $(CLOSURE) $(REQS) $(FLOWTARGET) --jscomp_warning=reportUnknownTypes >/dev/null; fi +.PHONY: tslint +tslint: $(TARGET) ## Run typescript checks + #@npm install dtslint typescript + @npm run-script dtslint + .PHONY: flow flow: lint ## Run flow checker @flow check --all --show-all-errors @@ -96,12 +107,6 @@ flow: lint ## Run flow checker .PHONY: cov cov: misc/coverage.html ## Run coverage test -#* To run coverage tests for one format, make cov_ -COVFMT=$(patsubst %,cov_%,$(FMT)) -.PHONY: $(COVFMT) -$(COVFMT): cov_%: - FMTS=$* make cov - misc/coverage.html: $(TARGET) test.js mocha --require blanket -R html-cov -t 20000 > $@ diff --git a/README.md b/README.md index cd7c423..a9dc7f2 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ var workbook = cfb.find('Workbook') # API -Typescript definitions are maintained in `misc/cfb.d.ts`. +Typescript definitions are maintained in `types/index.d.ts`. The CFB object exposes the following methods and properties: diff --git a/bin/cfb.njs b/bin/cfb.njs index 5c5ac01..e8fa302 100755 --- a/bin/cfb.njs +++ b/bin/cfb.njs @@ -25,12 +25,12 @@ if(program.dump) { console.log("Full Path Directory:"); console.log(cfb.FullPathDir); } -if(!program.quiet && !program.dump) for(var i=0; i!=cfb.FullPaths.length; ++i) { +if(!program.quiet && !program.dump) for(var i=0; i!==cfb.FullPaths.length; ++i) { if(cfb.FullPaths[i].slice(-1) === "/") { console.error("mkdir " + cfb.FullPaths[i]); fs.mkdirSync(cfb.FullPaths[i]); } else { console.error("writing " + cfb.FullPaths[i]); - fs.writeFileSync(cfb.FullPaths[i], cfb.FileIndex[i].content); + fs.writeFileSync(cfb.FullPaths[i], /*::new Buffer((*/cfb.FileIndex[i].content/*:: :any))*/); } } diff --git a/bits/08_blob.js b/bits/08_blob.js index 65aac31..c909c3d 100644 --- a/bits/08_blob.js +++ b/bits/08_blob.js @@ -1,10 +1,10 @@ var Base64 = (function(){ var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; return { - decode: function(input) { + decode: function(input/*:string*/)/*:string*/ { var o = ""; - var c1, c2, c3; - var e1, e2, e3, e4; + var c1/*:number*/, c2/*:number*/, c3/*:number*/; + var e1/*:number*/, e2/*:number*/, e3/*:number*/, e4/*:number*/; input = input.replace(/[^\w\+\/\=]/g, ""); for(var i = 0; i < input.length;) { e1 = map.indexOf(input.charAt(i++)); @@ -27,37 +27,45 @@ var Base64 = (function(){ var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/; -var s2a, _s2a; -s2a = _s2a = function _s2a(s/*:string*/) { return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); }; -var __toBuffer, ___toBuffer; -__toBuffer = ___toBuffer = function(bufs/*:any*/) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; -var __utf16le, ___utf16le; -__utf16le = ___utf16le = function(b,s,e) { var ss=[]; for(var i=s; i >*/)/*:RawBytes*/ { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; +var ___toBuffer = __toBuffer; +var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array*/=[]; for(var i=s; i*/=[]; for(var i=s; i*/)/*:RawBytes*/ { + if(Array.isArray(bufs[0])/*:: && bufs[0] instanceof Array*/) return /*::(*/[].concat.apply([], bufs)/*:: :any)*/; + var maxlen = 0, i = 0; + for(i = 0; i < bufs.length; ++i) maxlen += bufs[i].length; + var o = new Uint8Array(maxlen); + for(i = 0, maxlen = 0; i < bufs.length; maxlen += bufs[i].length, ++i) o.set(bufs[i], maxlen); + return o; +}; +var bconcat = __bconcat; if(typeof Buffer !== "undefined") { - __utf16le = function(b,s,e) { - if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); + __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { + if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'').replace(chr1,'!'); }; - __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; - __toBuffer = function(bufs/*:any*/) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; - s2a = function(s/*:string*/) { return new Buffer(s, "binary"); }; - bconcat = function(bufs/*:any*/) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; + __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; + __toBuffer = function(bufs/*:Array>*/)/*:RawBytes*/ { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat((bufs[0]/*:any*/)) : ___toBuffer(bufs);}; + s2a = function(s/*:string*/)/*:RawBytes*/ { return new Buffer(s, "binary"); }; + bconcat = function(bufs/*:Array*/)/*:RawBytes*/ { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(/*::(*/bufs/*:: :any)*/) : __bconcat(bufs); }; } -var __readUInt8 = function(b, idx) { return b[idx]; }; -var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; }; -var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; }; -var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; -var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; +var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; }; +var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; }; +var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; }; +var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; +var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; -function ReadShift(size/*:number*/, t/*:?any*/) { - var oI, oS, type = 0; +function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ { + var oI/*:: :number = 0*/, oS/*:: :string = ""*/, type = 0; switch(size) { case 1: oI = __readUInt8(this, this.l); break; case 2: oI = (t !== 'i' ? __readUInt16LE : __readInt16LE)(this, this.l); break; @@ -67,15 +75,15 @@ function ReadShift(size/*:number*/, t/*:?any*/) { this.l+=size; if(type === 0) return oI; return oS; } -function CheckField(hexstr/*:string*/, fld/*:string*/) { +function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ { var m = __hexlify(this,this.l,hexstr.length>>1); if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m); this.l += hexstr.length>>1; } -function prep_blob(blob/*:any*/, pos/*:number*/) { +function prep_blob(blob/*:CFBlob*/, pos/*:number*/)/*:void*/ { blob.l = pos; - blob.read_shift = ReadShift; + blob.read_shift = /*::(*/ReadShift/*:: :any)*/; blob.chk = CheckField; } diff --git a/bits/10_types.js b/bits/10_types.js index a7cc6ae..0c011aa 100644 --- a/bits/10_types.js +++ b/bits/10_types.js @@ -1,10 +1,15 @@ /*:: -declare var DO_NOT_EXPORT_CFB:any; -type SectorEntry = any; +declare var DO_NOT_EXPORT_CFB:?boolean; +type SectorEntry = { + name?:string; + nodes?:Array; + data:RawBytes; +}; type SectorList = { - (k:string|number):SectorEntry; + [k:string|number]:SectorEntry; name:?string; - fat_addrs:any; + fat_addrs:Array; ssz:number; } +type CFBFiles = {[n:string]:CFBEntry}; */ diff --git a/bits/30_cfbheader.js b/bits/30_cfbheader.js index d145964..52e13d6 100644 --- a/bits/30_cfbheader.js +++ b/bits/30_cfbheader.js @@ -1,3 +1,3 @@ /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ -var exports = {}; +var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; diff --git a/bits/31_version.js b/bits/31_version.js index 2b00ec2..dd07128 100644 --- a/bits/31_version.js +++ b/bits/31_version.js @@ -1 +1 @@ -exports.version = '0.11.1'; +exports.version = '0.12.0'; diff --git a/bits/40_parse.js b/bits/40_parse.js index 09e33dd..98eff26 100644 --- a/bits/40_parse.js +++ b/bits/40_parse.js @@ -1,4 +1,4 @@ -function parse(file) { +function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -7,10 +7,10 @@ var dir_start = 0; // first directory sector location var minifat_start = 0; // first mini FAT sector location var difat_start = 0; // first mini FAT sector location -var fat_addrs = []; // locations of FAT sectors +var fat_addrs/*:Array*/ = []; // locations of FAT sectors /* [MS-CFB] 2.2 Compound File Header */ -var blob/*:any*/ = file.slice(0,512); +var blob/*:CFBlob*/ = /*::(*/file.slice(0,512)/*:: :any)*/; prep_blob(blob, 0); /* major version */ @@ -22,14 +22,14 @@ switch(mver) { } /* reprocess header */ -if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); } +if(ssz !== 512) { blob = /*::(*/file.slice(0,ssz)/*:: :any)*/; prep_blob(blob, 28 /* blob.l */); } /* Save header for final object */ -var header = file.slice(0,ssz); +var header/*:RawBytes*/ = file.slice(0,ssz); check_shifts(blob, mver); // Number of Directory Sectors -var nds = blob.read_shift(4, 'i'); +var nds/*:number*/ = blob.read_shift(4, 'i'); if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds); // Number of FAT Sectors @@ -58,14 +58,14 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; } /** Break the file up into sectors */ -var sectors = sectorify(file, ssz); +var sectors/*:Array*/ = sectorify(file, ssz); sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs); @@ -79,13 +79,12 @@ sector_list.fat_addrs = fat_addrs; sector_list.ssz = ssz; /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -var files = {}, Paths/*:any*/ = [], FileIndex = [], FullPaths = [], FullPathDir = {}; +var files/*:CFBFiles*/ = {}, Paths/*:Array*/ = [], FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array*/ = [], FullPathDir = {}; read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); build_full_paths(FileIndex, FullPathDir, FullPaths, Paths); -var root_name = Paths.shift(); -Paths.root = root_name; +var root_name/*:string*/ = Paths.shift(); /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); diff --git a/bits/41_mver.js b/bits/41_mver.js index 75193f7..8f5f257 100644 --- a/bits/41_mver.js +++ b/bits/41_mver.js @@ -1,5 +1,5 @@ /* [MS-CFB] 2.2 Compound File Header -- read up to major version */ -function check_get_mver(blob) { +function check_get_mver(blob/*:CFBlob*/)/*:[number, number]*/ { // header signature 8 blob.chk(HEADER_SIGNATURE, 'Header Signature: '); @@ -7,11 +7,11 @@ function check_get_mver(blob) { blob.chk(HEADER_CLSID, 'CLSID: '); // minor version 2 - var mver = blob.read_shift(2, 'u'); + var mver/*:number*/ = blob.read_shift(2, 'u'); return [blob.read_shift(2,'u'), mver]; } -function check_shifts(blob, mver) { +function check_shifts(blob/*:CFBlob*/, mver/*:number*/)/*:void*/ { var shift = 0x09; // Byte Order diff --git a/bits/42_sectorify.js b/bits/42_sectorify.js index b778af7..7179e18 100644 --- a/bits/42_sectorify.js +++ b/bits/42_sectorify.js @@ -1,7 +1,7 @@ /** Break the file up into sectors */ -function sectorify(file, ssz) { +function sectorify(file/*:RawBytes*/, ssz/*:number*/)/*:Array*/ { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + var sectors/*:Array*/ = []; for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz); sectors[nsectors-1] = file.slice(nsectors*ssz); return sectors; diff --git a/bits/43_rbtree.js b/bits/43_rbtree.js index 7354d46..9f9e58f 100644 --- a/bits/43_rbtree.js +++ b/bits/43_rbtree.js @@ -1,7 +1,7 @@ /* [MS-CFB] 2.6.4 Red-Black Tree */ -function build_full_paths(FI, FPD, FP, Paths) { +function build_full_paths(FI/*:CFBFileIndex*/, FPD/*:CFBFullPathDir*/, FP/*:Array*/, Paths/*:Array*/)/*:void*/ { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad/*:Array*/ = [], q/*:Array*/ = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } diff --git a/bits/44_findpath.js b/bits/44_findpath.js index 4d1c856..910ade5 100644 --- a/bits/44_findpath.js +++ b/bits/44_findpath.js @@ -1,15 +1,15 @@ /* [MS-CFB] 2.6.4 */ -function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; +function make_find_path(FullPaths/*:Array*/, Paths/*:Array*/, FileIndex/*:CFBFileIndex*/, files/*:CFBFiles*/, root_name/*:string*/)/*:CFBFindPath*/ { + var UCFullPaths/*:Array*/ = []; + var UCPaths/*:Array*/ = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); - return function find_path(path/*:string*/) { - var k; + return function find_path(path/*:string*/)/*:?CFBEntry*/ { + var k/*:boolean*/ = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; - var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); - var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); + var UCPath/*:string*/ = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); + var w/*:number*/ = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); if(w === -1) return null; return k === true ? FileIndex[w] : files[Paths[w]]; }; diff --git a/bits/45_readfat.js b/bits/45_readfat.js index 0ece1a2..8866a40 100644 --- a/bits/45_readfat.js +++ b/bits/45_readfat.js @@ -1,7 +1,7 @@ /** 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, sectors, ssz, fat_addrs) { - var q; +function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array*/, ssz/*:number*/, fat_addrs)/*:void*/ { + var q/*:number*/ = ENDOFCHAIN; if(idx === ENDOFCHAIN) { if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { @@ -16,13 +16,11 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { } /** Follow the linked list of sectors for a given starting point */ -function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { +function get_sector_list(sectors/*:Array*/, start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/, chkd/*:?Array*/)/*:SectorEntry*/ { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf/*:Array*/ = [], buf_chain/*:Array*/ = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; @@ -37,26 +35,26 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { } /** Chase down the sector linked lists */ -function make_sector_list(sectors, dir_start, fat_addrs, ssz/*:number*/)/*:any*/ { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; +function make_sector_list(sectors/*:Array*/, dir_start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/)/*:SectorList*/ { + var sl = sectors.length, sector_list/*:SectorList*/ = ([]/*:any*/); + var chkd/*:Array*/ = [], buf/*:Array*/ = [], buf_chain/*:Array*/ = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]/*:Array*/); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; buf[buf.length] = j; buf_chain.push(sectors[j]); - var addr = fat_addrs[Math.floor(j*4/ssz)]; + var addr/*:number*/ = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}/*:SectorEntry*/); } return sector_list; } diff --git a/bits/46_readdir.js b/bits/46_readdir.js index 748d056..82b5d0f 100644 --- a/bits/46_readdir.js +++ b/bits/46_readdir.js @@ -1,17 +1,16 @@ /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; +function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sectors/*:Array*/, Paths/*:Array*/, nmfs, files, FileIndex) { var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob/*:CFBlob*/ = /*::(*/sector.slice(i, i+128)/*:: :any)*/; prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o/*:CFBEntry*/ = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -19,16 +18,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') - }/*:any*/); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 + }); + var ctime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -39,12 +36,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)/*:any*/); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)/*:any*/); prep_blob(o.content, 0); } } @@ -53,7 +50,7 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil } } -function read_date(blob, offset) { +function read_date(blob/*:RawBytes|CFBlob*/, offset/*:number*/)/*:Date*/ { return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000); } diff --git a/bits/49_readutils.js b/bits/49_readutils.js index c942f95..49d55e6 100644 --- a/bits/49_readutils.js +++ b/bits/49_readutils.js @@ -1,15 +1,15 @@ -var fs; -function readFileSync(filename/*:string*/, options/*:any*/) { - if(fs === undefined) fs = require('fs'); +var fs/*:: = require('fs'); */; +function readFileSync(filename/*:string*/, options/*:CFBReadOpts*/) { + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } -function readSync(blob/*:any*/, options/*:any*/) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { - case "file": return readFileSync(blob, options); - case "base64": return parse(s2a(Base64.decode(blob)), options); - case "binary": return parse(s2a(blob), options); +function readSync(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) { + switch(options && options.type || "base64") { + case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return readFileSync(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(blob); + return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options); } diff --git a/cfb.flow.js b/cfb.flow.js index 0998b22..9b16f2d 100644 --- a/cfb.flow.js +++ b/cfb.flow.js @@ -5,10 +5,10 @@ var Base64 = (function(){ var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; return { - decode: function(input) { + decode: function(input/*:string*/)/*:string*/ { var o = ""; - var c1, c2, c3; - var e1, e2, e3, e4; + var c1/*:number*/, c2/*:number*/, c3/*:number*/; + var e1/*:number*/, e2/*:number*/, e3/*:number*/, e4/*:number*/; input = input.replace(/[^\w\+\/\=]/g, ""); for(var i = 0; i < input.length;) { e1 = map.indexOf(input.charAt(i++)); @@ -31,37 +31,45 @@ var Base64 = (function(){ var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/; -var s2a, _s2a; -s2a = _s2a = function _s2a(s/*:string*/) { return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); }; -var __toBuffer, ___toBuffer; -__toBuffer = ___toBuffer = function(bufs/*:any*/) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; -var __utf16le, ___utf16le; -__utf16le = ___utf16le = function(b,s,e) { var ss=[]; for(var i=s; i >*/)/*:RawBytes*/ { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; +var ___toBuffer = __toBuffer; +var __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { var ss/*:Array*/=[]; for(var i=s; i*/=[]; for(var i=s; i*/)/*:RawBytes*/ { + if(Array.isArray(bufs[0])/*:: && bufs[0] instanceof Array*/) return /*::(*/[].concat.apply([], bufs)/*:: :any)*/; + var maxlen = 0, i = 0; + for(i = 0; i < bufs.length; ++i) maxlen += bufs[i].length; + var o = new Uint8Array(maxlen); + for(i = 0, maxlen = 0; i < bufs.length; maxlen += bufs[i].length, ++i) o.set(bufs[i], maxlen); + return o; +}; +var bconcat = __bconcat; if(typeof Buffer !== "undefined") { - __utf16le = function(b,s,e) { - if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); + __utf16le = function(b/*:RawBytes|CFBlob*/,s/*:number*/,e/*:number*/)/*:string*/ { + if(!Buffer.isBuffer(b)/*:: || !(b instanceof Buffer)*/) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'').replace(chr1,'!'); }; - __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; - __toBuffer = function(bufs/*:any*/) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; - s2a = function(s/*:string*/) { return new Buffer(s, "binary"); }; - bconcat = function(bufs/*:any*/) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; + __hexlify = function(b/*:RawBytes|CFBlob*/,s/*:number*/,l/*:number*/)/*:string*/ { return Buffer.isBuffer(b)/*:: && b instanceof Buffer*/ ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; + __toBuffer = function(bufs/*:Array>*/)/*:RawBytes*/ { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat((bufs[0]/*:any*/)) : ___toBuffer(bufs);}; + s2a = function(s/*:string*/)/*:RawBytes*/ { return new Buffer(s, "binary"); }; + bconcat = function(bufs/*:Array*/)/*:RawBytes*/ { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(/*::(*/bufs/*:: :any)*/) : __bconcat(bufs); }; } -var __readUInt8 = function(b, idx) { return b[idx]; }; -var __readUInt16LE = function(b, idx) { return b[idx+1]*(1<<8)+b[idx]; }; -var __readInt16LE = function(b, idx) { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; }; -var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; -var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; +var __readUInt8 = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx]; }; +var __readUInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+1]*(1<<8)+b[idx]; }; +var __readInt16LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { var u = b[idx+1]*(1<<8)+b[idx]; return (u < 0x8000) ? u : (0xffff - u + 1) * -1; }; +var __readUInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; +var __readInt32LE = function(b/*:RawBytes|CFBlob*/, idx/*:number*/)/*:number*/ { return (b[idx+3]<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; -function ReadShift(size/*:number*/, t/*:?any*/) { - var oI, oS, type = 0; +function ReadShift(size/*:number*/, t/*:?string*/)/*:number|string*/ { + var oI/*:: :number = 0*/, oS/*:: :string = ""*/, type = 0; switch(size) { case 1: oI = __readUInt8(this, this.l); break; case 2: oI = (t !== 'i' ? __readUInt16LE : __readInt16LE)(this, this.l); break; @@ -71,33 +79,38 @@ function ReadShift(size/*:number*/, t/*:?any*/) { this.l+=size; if(type === 0) return oI; return oS; } -function CheckField(hexstr/*:string*/, fld/*:string*/) { +function CheckField(hexstr/*:string*/, fld/*:string*/)/*:void*/ { var m = __hexlify(this,this.l,hexstr.length>>1); if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m); this.l += hexstr.length>>1; } -function prep_blob(blob/*:any*/, pos/*:number*/) { +function prep_blob(blob/*:CFBlob*/, pos/*:number*/)/*:void*/ { blob.l = pos; - blob.read_shift = ReadShift; + blob.read_shift = /*::(*/ReadShift/*:: :any)*/; blob.chk = CheckField; } /*:: -declare var DO_NOT_EXPORT_CFB:any; -type SectorEntry = any; +declare var DO_NOT_EXPORT_CFB:?boolean; +type SectorEntry = { + name?:string; + nodes?:Array; + data:RawBytes; +}; type SectorList = { - (k:string|number):SectorEntry; + [k:string|number]:SectorEntry; name:?string; - fat_addrs:any; + fat_addrs:Array; ssz:number; } +type CFBFiles = {[n:string]:CFBEntry}; */ /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ -var exports = {}; -exports.version = '0.11.1'; -function parse(file) { +var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; +exports.version = '0.12.0'; +function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -106,10 +119,10 @@ var dir_start = 0; // first directory sector location var minifat_start = 0; // first mini FAT sector location var difat_start = 0; // first mini FAT sector location -var fat_addrs = []; // locations of FAT sectors +var fat_addrs/*:Array*/ = []; // locations of FAT sectors /* [MS-CFB] 2.2 Compound File Header */ -var blob/*:any*/ = file.slice(0,512); +var blob/*:CFBlob*/ = /*::(*/file.slice(0,512)/*:: :any)*/; prep_blob(blob, 0); /* major version */ @@ -121,14 +134,14 @@ switch(mver) { } /* reprocess header */ -if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); } +if(ssz !== 512) { blob = /*::(*/file.slice(0,ssz)/*:: :any)*/; prep_blob(blob, 28 /* blob.l */); } /* Save header for final object */ -var header = file.slice(0,ssz); +var header/*:RawBytes*/ = file.slice(0,ssz); check_shifts(blob, mver); // Number of Directory Sectors -var nds = blob.read_shift(4, 'i'); +var nds/*:number*/ = blob.read_shift(4, 'i'); if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds); // Number of FAT Sectors @@ -157,14 +170,14 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; } /** Break the file up into sectors */ -var sectors = sectorify(file, ssz); +var sectors/*:Array*/ = sectorify(file, ssz); sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs); @@ -178,13 +191,12 @@ sector_list.fat_addrs = fat_addrs; sector_list.ssz = ssz; /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -var files = {}, Paths/*:any*/ = [], FileIndex = [], FullPaths = [], FullPathDir = {}; +var files/*:CFBFiles*/ = {}, Paths/*:Array*/ = [], FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array*/ = [], FullPathDir = {}; read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); build_full_paths(FileIndex, FullPathDir, FullPaths, Paths); -var root_name = Paths.shift(); -Paths.root = root_name; +var root_name/*:string*/ = Paths.shift(); /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); @@ -199,7 +211,7 @@ return { } // parse /* [MS-CFB] 2.2 Compound File Header -- read up to major version */ -function check_get_mver(blob) { +function check_get_mver(blob/*:CFBlob*/)/*:[number, number]*/ { // header signature 8 blob.chk(HEADER_SIGNATURE, 'Header Signature: '); @@ -207,11 +219,11 @@ function check_get_mver(blob) { blob.chk(HEADER_CLSID, 'CLSID: '); // minor version 2 - var mver = blob.read_shift(2, 'u'); + var mver/*:number*/ = blob.read_shift(2, 'u'); return [blob.read_shift(2,'u'), mver]; } -function check_shifts(blob, mver) { +function check_shifts(blob/*:CFBlob*/, mver/*:number*/)/*:void*/ { var shift = 0x09; // Byte Order @@ -233,18 +245,18 @@ function check_shifts(blob, mver) { } /** Break the file up into sectors */ -function sectorify(file, ssz) { +function sectorify(file/*:RawBytes*/, ssz/*:number*/)/*:Array*/ { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + var sectors/*:Array*/ = []; for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz); sectors[nsectors-1] = file.slice(nsectors*ssz); return sectors; } /* [MS-CFB] 2.6.4 Red-Black Tree */ -function build_full_paths(FI, FPD, FP, Paths) { +function build_full_paths(FI/*:CFBFileIndex*/, FPD/*:CFBFullPathDir*/, FP/*:Array*/, Paths/*:Array*/)/*:void*/ { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad/*:Array*/ = [], q/*:Array*/ = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -283,17 +295,17 @@ function build_full_paths(FI, FPD, FP, Paths) { } /* [MS-CFB] 2.6.4 */ -function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; +function make_find_path(FullPaths/*:Array*/, Paths/*:Array*/, FileIndex/*:CFBFileIndex*/, files/*:CFBFiles*/, root_name/*:string*/)/*:CFBFindPath*/ { + var UCFullPaths/*:Array*/ = []; + var UCPaths/*:Array*/ = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); - return function find_path(path/*:string*/) { - var k; + return function find_path(path/*:string*/)/*:?CFBEntry*/ { + var k/*:boolean*/ = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; - var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); - var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); + var UCPath/*:string*/ = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); + var w/*:number*/ = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); if(w === -1) return null; return k === true ? FileIndex[w] : files[Paths[w]]; }; @@ -301,8 +313,8 @@ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { /** 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, sectors, ssz, fat_addrs) { - var q; +function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array*/, ssz/*:number*/, fat_addrs)/*:void*/ { + var q/*:number*/ = ENDOFCHAIN; if(idx === ENDOFCHAIN) { if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { @@ -317,13 +329,11 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { } /** Follow the linked list of sectors for a given starting point */ -function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { +function get_sector_list(sectors/*:Array*/, start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/, chkd/*:?Array*/)/*:SectorEntry*/ { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf/*:Array*/ = [], buf_chain/*:Array*/ = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; @@ -338,44 +348,43 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { } /** Chase down the sector linked lists */ -function make_sector_list(sectors, dir_start, fat_addrs, ssz/*:number*/)/*:any*/ { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; +function make_sector_list(sectors/*:Array*/, dir_start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/)/*:SectorList*/ { + var sl = sectors.length, sector_list/*:SectorList*/ = ([]/*:any*/); + var chkd/*:Array*/ = [], buf/*:Array*/ = [], buf_chain/*:Array*/ = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]/*:Array*/); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; buf[buf.length] = j; buf_chain.push(sectors[j]); - var addr = fat_addrs[Math.floor(j*4/ssz)]; + var addr/*:number*/ = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}/*:SectorEntry*/); } return sector_list; } /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; +function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sectors/*:Array*/, Paths/*:Array*/, nmfs, files, FileIndex) { var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob/*:CFBlob*/ = /*::(*/sector.slice(i, i+128)/*:: :any)*/; prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o/*:CFBEntry*/ = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -383,16 +392,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') - }/*:any*/); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 + }); + var ctime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -403,12 +410,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)/*:any*/); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)/*:any*/); prep_blob(o.content, 0); } } @@ -417,23 +424,23 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil } } -function read_date(blob, offset) { +function read_date(blob/*:RawBytes|CFBlob*/, offset/*:number*/)/*:Date*/ { return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000); } -var fs; -function readFileSync(filename/*:string*/, options/*:any*/) { - if(fs === undefined) fs = require('fs'); +var fs/*:: = require('fs'); */; +function readFileSync(filename/*:string*/, options/*:CFBReadOpts*/) { + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } -function readSync(blob/*:any*/, options/*:any*/) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { - case "file": return readFileSync(blob, options); - case "base64": return parse(s2a(Base64.decode(blob)), options); - case "binary": return parse(s2a(blob), options); +function readSync(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) { + switch(options && options.type || "base64") { + case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return readFileSync(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(blob); + return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options); } /** CFB Constants */ diff --git a/cfb.js b/cfb.js index 17bb8a5..3df9d36 100644 --- a/cfb.js +++ b/cfb.js @@ -31,15 +31,23 @@ var Base64 = (function(){ var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/; -var s2a, _s2a; -s2a = _s2a = function _s2a(s) { return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); }; -var __toBuffer, ___toBuffer; -__toBuffer = ___toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; -var __utf16le, ___utf16le; -__utf16le = ___utf16le = function(b,s,e) { var ss=[]; for(var i=s; i 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; + __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat((bufs[0])) : ___toBuffer(bufs);}; s2a = function(s) { return new Buffer(s, "binary"); }; - bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; + bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : __bconcat(bufs); }; } @@ -86,8 +94,8 @@ function prep_blob(blob, pos) { /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '0.11.1'; -function parse(file) { +exports.version = '0.12.0'; +function parse(file, options) { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -147,7 +155,7 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; @@ -174,7 +182,6 @@ read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); 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) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); @@ -225,7 +232,7 @@ function check_shifts(blob, mver) { /** Break the file up into sectors */ function sectorify(file, ssz) { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + 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); return sectors; @@ -234,7 +241,7 @@ function sectorify(file, ssz) { /* [MS-CFB] 2.6.4 Red-Black Tree */ function build_full_paths(FI, FPD, FP, Paths) { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad = [], q = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -274,12 +281,12 @@ function build_full_paths(FI, FPD, FP, Paths) { /* [MS-CFB] 2.6.4 */ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; + var UCFullPaths = []; + var UCPaths = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); return function find_path(path) { - var k; + var k = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); @@ -292,7 +299,7 @@ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { /** 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, sectors, ssz, fat_addrs) { - var q; + var q = ENDOFCHAIN; if(idx === ENDOFCHAIN) { if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { @@ -309,11 +316,9 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { /** Follow the linked list of sectors for a given starting point */ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf = [], buf_chain = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; @@ -329,13 +334,13 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { /** Chase down the sector linked lists */ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; + var sl = sectors.length, sector_list = ([]); + var chkd = [], buf = [], buf_chain = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; @@ -347,25 +352,24 @@ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}); } return sector_list; } /* [MS-CFB] 2.6.1 Compound File Directory Entry */ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob = sector.slice(i, i+128); prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -373,16 +377,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 }); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -393,12 +395,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)); prep_blob(o.content, 0); } } @@ -413,17 +415,17 @@ function read_date(blob, offset) { var fs; function readFileSync(filename, options) { - if(fs === undefined) fs = require('fs'); + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } function readSync(blob, options) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { + switch(options && options.type || "base64") { case "file": return readFileSync(blob, options); case "base64": return parse(s2a(Base64.decode(blob)), options); case "binary": return parse(s2a(blob), options); } - return parse(blob); + return parse(blob, options); } /** CFB Constants */ diff --git a/dist/cfb.js b/dist/cfb.js index 7a2127f..3df9d36 100644 --- a/dist/cfb.js +++ b/dist/cfb.js @@ -31,15 +31,23 @@ var Base64 = (function(){ var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/; -var s2a, _s2a; -s2a = _s2a = function _s2a(s) { return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); }; -var __toBuffer, ___toBuffer; -__toBuffer = ___toBuffer = function(bufs) { var x = []; for(var i = 0; i < bufs[0].length; ++i) { x.push.apply(x, bufs[0][i]); } return x; }; -var __utf16le, ___utf16le; -__utf16le = ___utf16le = function(b,s,e) { var ss=[]; for(var i=s; i 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; + __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat((bufs[0])) : ___toBuffer(bufs);}; s2a = function(s) { return new Buffer(s, "binary"); }; - bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; + bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : __bconcat(bufs); }; } @@ -73,7 +81,7 @@ function ReadShift(size, t) { function CheckField(hexstr, fld) { var m = __hexlify(this,this.l,hexstr.length>>1); - if(m !== hexstr) throw fld + 'Expected ' + hexstr + ' saw ' + m; + if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m); this.l += hexstr.length>>1; } @@ -86,8 +94,8 @@ function prep_blob(blob, pos) { /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '0.11.0'; -function parse(file) { +exports.version = '0.12.0'; +function parse(file, options) { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -107,7 +115,7 @@ var mv = check_get_mver(blob); mver = mv[0]; switch(mver) { case 3: ssz = 512; break; case 4: ssz = 4096; break; - default: throw "Major Version: Expected 3 or 4 saw " + mver; + default: throw new Error("Major Version: Expected 3 or 4 saw " + mver); } /* reprocess header */ @@ -119,7 +127,7 @@ check_shifts(blob, mver); // Number of Directory Sectors var nds = blob.read_shift(4, 'i'); -if(mver === 3 && nds !== 0) throw '# Directory Sectors: Expected 0 saw ' + nds; +if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds); // Number of FAT Sectors //var nfs = blob.read_shift(4, 'i'); @@ -147,7 +155,7 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; @@ -174,7 +182,6 @@ read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); 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) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); @@ -205,13 +212,14 @@ function check_shifts(blob, mver) { var shift = 0x09; // Byte Order - blob.chk('feff', 'Byte Order: '); + //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff + blob.l += 2; // Sector Shift switch((shift = blob.read_shift(2))) { - case 0x09: if(mver !== 3) throw 'MajorVersion/SectorShift Mismatch'; break; - case 0x0c: if(mver !== 4) throw 'MajorVersion/SectorShift Mismatch'; break; - default: throw 'Sector Shift: Expected 9 or 12 saw ' + shift; + case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break; + case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break; + default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift); } // Mini Sector Shift @@ -224,7 +232,7 @@ function check_shifts(blob, mver) { /** Break the file up into sectors */ function sectorify(file, ssz) { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + 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); return sectors; @@ -233,7 +241,7 @@ function sectorify(file, ssz) { /* [MS-CFB] 2.6.4 Red-Black Tree */ function build_full_paths(FI, FPD, FP, Paths) { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad = [], q = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -273,12 +281,12 @@ function build_full_paths(FI, FPD, FP, Paths) { /* [MS-CFB] 2.6.4 */ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; + var UCFullPaths = []; + var UCPaths = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); return function find_path(path) { - var k; + var k = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); @@ -291,9 +299,9 @@ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { /** 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, sectors, ssz, fat_addrs) { - var q; + var q = ENDOFCHAIN; if(idx === ENDOFCHAIN) { - if(cnt !== 0) throw "DIFAT chain shorter than expected"; + if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { var sector = sectors[idx], m = (ssz>>>2)-1; if(!sector) return; @@ -308,18 +316,16 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { /** Follow the linked list of sectors for a given starting point */ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf = [], buf_chain = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; buf_chain.push(sectors[j]); var addr = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); - if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz; + if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } @@ -328,13 +334,13 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { /** Chase down the sector linked lists */ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; + var sl = sectors.length, sector_list = ([]); + var chkd = [], buf = [], buf_chain = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; @@ -342,29 +348,28 @@ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { buf_chain.push(sectors[j]); var addr = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); - if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz; + if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}); } return sector_list; } /* [MS-CFB] 2.6.1 Compound File Directory Entry */ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob = sector.slice(i, i+128); prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -372,16 +377,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 }); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -392,12 +395,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)); prep_blob(o.content, 0); } } @@ -412,17 +415,17 @@ function read_date(blob, offset) { var fs; function readFileSync(filename, options) { - if(fs === undefined) fs = require('fs'); + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } function readSync(blob, options) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { + switch(options && options.type || "base64") { case "file": return readFileSync(blob, options); case "base64": return parse(s2a(Base64.decode(blob)), options); case "binary": return parse(s2a(blob), options); } - return parse(blob); + return parse(blob, options); } /** CFB Constants */ diff --git a/dist/cfb.min.js b/dist/cfb.min.js index 5168f2a..7551704 100644 --- a/dist/cfb.min.js +++ b/dist/cfb.min.js @@ -1,2 +1,2 @@ /* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */ -var Base64=function(){var map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{decode:function(input){var o="";var c1,c2,c3;var e1,e2,e3,e4;input=input.replace(/[^\w\+\/\=]/g,"");for(var i=0;i>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 chr0=/\u0000/g,chr1=/[\u0001-\u0006]/;var s2a,_s2a;s2a=_s2a=function _s2a(s){return s.split("").map(function(x){return x.charCodeAt(0)&255})};var __toBuffer,___toBuffer;__toBuffer=___toBuffer=function(bufs){var x=[];for(var i=0;i0&&Buffer.isBuffer(bufs[0][0])?Buffer.concat(bufs[0]):___toBuffer(bufs)};s2a=function(s){return new Buffer(s,"binary")};bconcat=function(bufs){return Buffer.isBuffer(bufs[0])?Buffer.concat(bufs):[].concat.apply([],bufs)}}var __readUInt8=function(b,idx){return b[idx]};var __readUInt16LE=function(b,idx){return b[idx+1]*(1<<8)+b[idx]};var __readInt16LE=function(b,idx){var u=b[idx+1]*(1<<8)+b[idx];return u<32768?u:(65535-u+1)*-1};var __readUInt32LE=function(b,idx){return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]};var __readInt32LE=function(b,idx){return(b[idx+3]<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]};function ReadShift(size,t){var oI,oS,type=0;switch(size){case 1:oI=__readUInt8(this,this.l);break;case 2:oI=(t!=="i"?__readUInt16LE:__readInt16LE)(this,this.l);break;case 4:oI=__readInt32LE(this,this.l);break;case 16:type=2;oS=__hexlify(this,this.l,size)}this.l+=size;if(type===0)return oI;return oS}function CheckField(hexstr,fld){var m=__hexlify(this,this.l,hexstr.length>>1);if(m!==hexstr)throw fld+"Expected "+hexstr+" saw "+m;this.l+=hexstr.length>>1}function prep_blob(blob,pos){blob.l=pos;blob.read_shift=ReadShift;blob.chk=CheckField}var CFB=function _CFB(){var exports={};exports.version="0.11.0";function parse(file){var mver=3;var ssz=512;var nmfs=0;var ndfs=0;var dir_start=0;var minifat_start=0;var difat_start=0;var fat_addrs=[];var blob=file.slice(0,512);prep_blob(blob,0);var mv=check_get_mver(blob);mver=mv[0];switch(mver){case 3:ssz=512;break;case 4:ssz=4096;break;default:throw"Major Version: Expected 3 or 4 saw "+mver}if(ssz!==512){blob=file.slice(0,ssz);prep_blob(blob,28)}var header=file.slice(0,ssz);check_shifts(blob,mver);var nds=blob.read_shift(4,"i");if(mver===3&&nds!==0)throw"# Directory Sectors: Expected 0 saw "+nds;blob.l+=4;dir_start=blob.read_shift(4,"i");blob.l+=4;blob.chk("00100000","Mini Stream Cutoff Size: ");minifat_start=blob.read_shift(4,"i");nmfs=blob.read_shift(4,"i");difat_start=blob.read_shift(4,"i");ndfs=blob.read_shift(4,"i");for(var q,j=0;j<109;++j){q=blob.read_shift(4,"i");if(q<0)break;fat_addrs[j]=q}var sectors=sectorify(file,ssz);sleuth_fat(difat_start,ndfs,sectors,ssz,fat_addrs);var sector_list=make_sector_list(sectors,dir_start,fat_addrs,ssz);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";sector_list.fat_addrs=fat_addrs;sector_list.ssz=ssz;var files={},Paths=[],FileIndex=[],FullPaths=[],FullPathDir={};read_directory(dir_start,sector_list,sectors,Paths,nmfs,files,FileIndex);build_full_paths(FileIndex,FullPathDir,FullPaths,Paths);var root_name=Paths.shift();Paths.root=root_name;var find_path=make_find_path(FullPaths,Paths,FileIndex,files,root_name);return{raw:{header:header,sectors:sectors},FileIndex:FileIndex,FullPaths:FullPaths,FullPathDir:FullPathDir,find:find_path}}function check_get_mver(blob){blob.chk(HEADER_SIGNATURE,"Header Signature: ");blob.chk(HEADER_CLSID,"CLSID: ");var mver=blob.read_shift(2,"u");return[blob.read_shift(2,"u"),mver]}function check_shifts(blob,mver){var shift=9;blob.chk("feff","Byte Order: ");switch(shift=blob.read_shift(2)){case 9:if(mver!==3)throw"MajorVersion/SectorShift Mismatch";break;case 12:if(mver!==4)throw"MajorVersion/SectorShift Mismatch";break;default:throw"Sector Shift: Expected 9 or 12 saw "+shift}blob.chk("0600","Mini Sector Shift: ");blob.chk("000000000000","Reserved: ")}function sectorify(file,ssz){var nsectors=Math.ceil(file.length/ssz)-1;var sectors=new Array(nsectors);for(var i=1;i>>2)-1;if(!sector)return;for(var i=0;i=0;){chkd[j]=true;buf[buf.length]=j;buf_chain.push(sectors[j]);var addr=fat_addrs[Math.floor(j*4/ssz)];jj=j*4&modulus;if(ssz<4+jj)throw"FAT boundary crossed: "+j+" 4 "+ssz;if(!sectors[addr])break;j=__readInt32LE(sectors[addr],jj)}return{nodes:buf,data:__toBuffer([buf_chain])}}function make_sector_list(sectors,dir_start,fat_addrs,ssz){var sl=sectors.length,sector_list=new Array(sl);var chkd=new Array(sl),buf,buf_chain;var modulus=ssz-1,i,j,k,jj;for(i=0;i=sl)k-=sl;if(chkd[k]===true)continue;buf_chain=[];for(j=k;j>=0;){chkd[j]=true;buf[buf.length]=j;buf_chain.push(sectors[j]);var addr=fat_addrs[Math.floor(j*4/ssz)];jj=j*4&modulus;if(ssz<4+jj)throw"FAT boundary crossed: "+j+" 4 "+ssz;if(!sectors[addr])break;j=__readInt32LE(sectors[addr],jj)}sector_list[k]={nodes:buf,data:__toBuffer([buf_chain])}}return sector_list}function read_directory(dir_start,sector_list,sectors,Paths,nmfs,files,FileIndex){var blob;var minifat_store=0,pl=Paths.length?2:0;var sector=sector_list[dir_start].data;var i=0,namelen=0,name,o,ctime,mtime;for(;i0&&minifat_store!==ENDOFCHAIN)sector_list[minifat_store].name="!StreamData"}else if(o.size>=4096){o.storage="fat";if(sector_list[o.start]===undefined)sector_list[o.start]=get_sector_list(sectors,o.start,sector_list.fat_addrs,sector_list.ssz);sector_list[o.start].name=o.name;o.content=sector_list[o.start].data.slice(0,o.size);prep_blob(o.content,0)}else{o.storage="minifat";if(minifat_store!==ENDOFCHAIN&&o.start!==ENDOFCHAIN){o.content=sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size);prep_blob(o.content,0)}}files[name]=o;FileIndex.push(o)}}function read_date(blob,offset){return new Date((__readUInt32LE(blob,offset+4)/1e7*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7-11644473600)*1e3)}var fs;function readFileSync(filename,options){if(fs===undefined)fs=require("fs");return parse(fs.readFileSync(filename),options)}function readSync(blob,options){switch(options!==undefined&&options.type!==undefined?options.type:"base64"){case"file":return readFileSync(blob,options);case"base64":return parse(s2a(Base64.decode(blob)),options);case"binary":return parse(s2a(blob),options)}return parse(blob)}var MSSZ=64;var ENDOFCHAIN=-2;var HEADER_SIGNATURE="d0cf11e0a1b11ae1";var HEADER_CLSID="00000000000000000000000000000000";var consts={MAXREGSECT:-6,DIFSECT:-4,FATSECT:-3,ENDOFCHAIN:ENDOFCHAIN,FREESECT:-1,HEADER_SIGNATURE:HEADER_SIGNATURE,HEADER_MINOR_VERSION:"3e00",MAXREGSID:-6,NOSTREAM:-1,HEADER_CLSID:HEADER_CLSID,EntryTypes:["unknown","storage","stream","lockbytes","property","root"]};exports.read=readSync;exports.parse=parse;exports.utils={ReadShift:ReadShift,CheckField:CheckField,prep_blob:prep_blob,bconcat:bconcat,consts:consts};return exports}();if(typeof require!=="undefined"&&typeof module!=="undefined"&&typeof DO_NOT_EXPORT_CFB==="undefined"){module.exports=CFB} +var Base64=function(){var map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{decode:function(input){var o="";var c1,c2,c3;var e1,e2,e3,e4;input=input.replace(/[^\w\+\/\=]/g,"");for(var i=0;i>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 chr0=/\u0000/g,chr1=/[\u0001-\u0006]/;var s2a=function _s2a(s){return s.split("").map(function(x){return x.charCodeAt(0)&255})};var _s2a=s2a;var __toBuffer=function(bufs){var x=[];for(var i=0;i0&&Buffer.isBuffer(bufs[0][0])?Buffer.concat(bufs[0]):___toBuffer(bufs)};s2a=function(s){return new Buffer(s,"binary")};bconcat=function(bufs){return Buffer.isBuffer(bufs[0])?Buffer.concat(bufs):__bconcat(bufs)}}var __readUInt8=function(b,idx){return b[idx]};var __readUInt16LE=function(b,idx){return b[idx+1]*(1<<8)+b[idx]};var __readInt16LE=function(b,idx){var u=b[idx+1]*(1<<8)+b[idx];return u<32768?u:(65535-u+1)*-1};var __readUInt32LE=function(b,idx){return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]};var __readInt32LE=function(b,idx){return(b[idx+3]<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]};function ReadShift(size,t){var oI,oS,type=0;switch(size){case 1:oI=__readUInt8(this,this.l);break;case 2:oI=(t!=="i"?__readUInt16LE:__readInt16LE)(this,this.l);break;case 4:oI=__readInt32LE(this,this.l);break;case 16:type=2;oS=__hexlify(this,this.l,size);}this.l+=size;if(type===0)return oI;return oS}function CheckField(hexstr,fld){var m=__hexlify(this,this.l,hexstr.length>>1);if(m!==hexstr)throw new Error(fld+"Expected "+hexstr+" saw "+m);this.l+=hexstr.length>>1}function prep_blob(blob,pos){blob.l=pos;blob.read_shift=ReadShift;blob.chk=CheckField}var CFB=function _CFB(){var exports={};exports.version="0.12.0";function parse(file,options){var mver=3;var ssz=512;var nmfs=0;var ndfs=0;var dir_start=0;var minifat_start=0;var difat_start=0;var fat_addrs=[];var blob=file.slice(0,512);prep_blob(blob,0);var mv=check_get_mver(blob);mver=mv[0];switch(mver){case 3:ssz=512;break;case 4:ssz=4096;break;default:throw new Error("Major Version: Expected 3 or 4 saw "+mver);}if(ssz!==512){blob=file.slice(0,ssz);prep_blob(blob,28)}var header=file.slice(0,ssz);check_shifts(blob,mver);var nds=blob.read_shift(4,"i");if(mver===3&&nds!==0)throw new Error("# Directory Sectors: Expected 0 saw "+nds);blob.l+=4;dir_start=blob.read_shift(4,"i");blob.l+=4;blob.chk("00100000","Mini Stream Cutoff Size: ");minifat_start=blob.read_shift(4,"i");nmfs=blob.read_shift(4,"i");difat_start=blob.read_shift(4,"i");ndfs=blob.read_shift(4,"i");for(var q=-1,j=0;j<109;++j){q=blob.read_shift(4,"i");if(q<0)break;fat_addrs[j]=q}var sectors=sectorify(file,ssz);sleuth_fat(difat_start,ndfs,sectors,ssz,fat_addrs);var sector_list=make_sector_list(sectors,dir_start,fat_addrs,ssz);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";sector_list.fat_addrs=fat_addrs;sector_list.ssz=ssz;var files={},Paths=[],FileIndex=[],FullPaths=[],FullPathDir={};read_directory(dir_start,sector_list,sectors,Paths,nmfs,files,FileIndex);build_full_paths(FileIndex,FullPathDir,FullPaths,Paths);var root_name=Paths.shift();var find_path=make_find_path(FullPaths,Paths,FileIndex,files,root_name);return{raw:{header:header,sectors:sectors},FileIndex:FileIndex,FullPaths:FullPaths,FullPathDir:FullPathDir,find:find_path}}function check_get_mver(blob){blob.chk(HEADER_SIGNATURE,"Header Signature: ");blob.chk(HEADER_CLSID,"CLSID: ");var mver=blob.read_shift(2,"u");return[blob.read_shift(2,"u"),mver]}function check_shifts(blob,mver){var shift=9;blob.l+=2;switch(shift=blob.read_shift(2)){case 9:if(mver!=3)throw new Error("Sector Shift: Expected 9 saw "+shift);break;case 12:if(mver!=4)throw new Error("Sector Shift: Expected 12 saw "+shift);break;default:throw new Error("Sector Shift: Expected 9 or 12 saw "+shift);}blob.chk("0600","Mini Sector Shift: ");blob.chk("000000000000","Reserved: ")}function sectorify(file,ssz){var nsectors=Math.ceil(file.length/ssz)-1;var sectors=[];for(var i=1;i>>2)-1;if(!sector)return;for(var i=0;i=0;){chkd[j]=true;buf[buf.length]=j;buf_chain.push(sectors[j]);var addr=fat_addrs[Math.floor(j*4/ssz)];jj=j*4&modulus;if(ssz<4+jj)throw new Error("FAT boundary crossed: "+j+" 4 "+ssz);if(!sectors[addr])break;j=__readInt32LE(sectors[addr],jj)}return{nodes:buf,data:__toBuffer([buf_chain])}}function make_sector_list(sectors,dir_start,fat_addrs,ssz){var sl=sectors.length,sector_list=[];var chkd=[],buf=[],buf_chain=[];var modulus=ssz-1,i=0,j=0,k=0,jj=0;for(i=0;i=sl)k-=sl;if(chkd[k])continue;buf_chain=[];for(j=k;j>=0;){chkd[j]=true;buf[buf.length]=j;buf_chain.push(sectors[j]);var addr=fat_addrs[Math.floor(j*4/ssz)];jj=j*4&modulus;if(ssz<4+jj)throw new Error("FAT boundary crossed: "+j+" 4 "+ssz);if(!sectors[addr])break;j=__readInt32LE(sectors[addr],jj)}sector_list[k]={nodes:buf,data:__toBuffer([buf_chain])}}return sector_list}function read_directory(dir_start,sector_list,sectors,Paths,nmfs,files,FileIndex){var minifat_store=0,pl=Paths.length?2:0;var sector=sector_list[dir_start].data;var i=0,namelen=0,name;for(;i0&&minifat_store!==ENDOFCHAIN)sector_list[minifat_store].name="!StreamData"}else if(o.size>=4096){o.storage="fat";if(sector_list[o.start]===undefined)sector_list[o.start]=get_sector_list(sectors,o.start,sector_list.fat_addrs,sector_list.ssz);sector_list[o.start].name=o.name;o.content=sector_list[o.start].data.slice(0,o.size);prep_blob(o.content,0)}else{o.storage="minifat";if(minifat_store!==ENDOFCHAIN&&o.start!==ENDOFCHAIN){o.content=sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size);prep_blob(o.content,0)}}files[name]=o;FileIndex.push(o)}}function read_date(blob,offset){return new Date((__readUInt32LE(blob,offset+4)/1e7*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7-11644473600)*1e3)}var fs;function readFileSync(filename,options){if(fs==null)fs=require("fs");return parse(fs.readFileSync(filename),options)}function readSync(blob,options){switch(options&&options.type||"base64"){case"file":return readFileSync(blob,options);case"base64":return parse(s2a(Base64.decode(blob)),options);case"binary":return parse(s2a(blob),options);}return parse(blob,options)}var MSSZ=64;var ENDOFCHAIN=-2;var HEADER_SIGNATURE="d0cf11e0a1b11ae1";var HEADER_CLSID="00000000000000000000000000000000";var consts={MAXREGSECT:-6,DIFSECT:-4,FATSECT:-3,ENDOFCHAIN:ENDOFCHAIN,FREESECT:-1,HEADER_SIGNATURE:HEADER_SIGNATURE,HEADER_MINOR_VERSION:"3e00",MAXREGSID:-6,NOSTREAM:-1,HEADER_CLSID:HEADER_CLSID,EntryTypes:["unknown","storage","stream","lockbytes","property","root"]};exports.read=readSync;exports.parse=parse;exports.utils={ReadShift:ReadShift,CheckField:CheckField,prep_blob:prep_blob,bconcat:bconcat,consts:consts};return exports}();if(typeof require!=="undefined"&&typeof module!=="undefined"&&typeof DO_NOT_EXPORT_CFB==="undefined"){module.exports=CFB} diff --git a/dist/cfb.min.map b/dist/cfb.min.map index 37a2b33..8fca5ce 100644 --- a/dist/cfb.min.map +++ b/dist/cfb.min.map @@ -1 +1 @@ -{"version":3,"sources":["cfb.js"],"names":["Base64","map","decode","input","o","c1","c2","c3","e1","e2","e3","e4","replace","i","length","indexOf","charAt","String","fromCharCode","chr0","chr1","s2a","_s2a","s","split","x","charCodeAt","__toBuffer","___toBuffer","bufs","push","apply","__utf16le","___utf16le","b","e","ss","__readUInt16LE","join","__hexlify","___hexlify","l","slice","toString","bconcat","concat","Buffer","isBuffer","__readUInt8","idx","__readInt16LE","u","__readUInt32LE","__readInt32LE","ReadShift","size","t","oI","oS","type","this","CheckField","hexstr","fld","m","prep_blob","blob","pos","read_shift","chk","CFB","_CFB","exports","version","parse","file","mver","ssz","nmfs","ndfs","dir_start","minifat_start","difat_start","fat_addrs","mv","check_get_mver","header","check_shifts","nds","q","j","sectors","sectorify","sleuth_fat","sector_list","make_sector_list","name","ENDOFCHAIN","files","Paths","FileIndex","FullPaths","FullPathDir","read_directory","build_full_paths","root_name","shift","root","find_path","make_find_path","raw","find","HEADER_SIGNATURE","HEADER_CLSID","nsectors","Math","ceil","Array","FI","FPD","FP","L","R","C","pl","dad","UCFullPaths","UCPaths","toUpperCase","path","k","UCPath","w","cnt","sector","get_sector_list","start","chkd","sl","buf","buf_chain","modulus","jj","addr","floor","nodes","data","minifat_store","namelen","ctime","mtime","color","clsid","state","ct","read_date","mt","storage","undefined","content","MSSZ","offset","Date","pow","fs","readFileSync","filename","options","require","readSync","consts","MAXREGSECT","DIFSECT","FATSECT","FREESECT","HEADER_MINOR_VERSION","MAXREGSID","NOSTREAM","EntryTypes","read","utils","module","DO_NOT_EXPORT_CFB"],"mappings":"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","file":"dist/cfb.min.js"} \ No newline at end of file +{"version":3,"sources":["cfb.js"],"names":["Base64","map","decode","input","o","c1","c2","c3","e1","e2","e3","e4","replace","i","length","indexOf","charAt","String","fromCharCode","chr0","chr1","s2a","_s2a","s","split","x","charCodeAt","__toBuffer","bufs","push","apply","___toBuffer","__utf16le","b","e","ss","__readUInt16LE","join","___utf16le","__hexlify","l","toString","slice","___hexlify","__bconcat","Array","isArray","concat","maxlen","Uint8Array","set","bconcat","Buffer","isBuffer","__readUInt8","idx","__readInt16LE","u","__readUInt32LE","__readInt32LE","ReadShift","size","t","oI","oS","type","this","CheckField","hexstr","fld","m","Error","prep_blob","blob","pos","read_shift","chk","CFB","_CFB","exports","version","parse","file","options","mver","ssz","nmfs","ndfs","dir_start","minifat_start","difat_start","fat_addrs","mv","check_get_mver","header","check_shifts","nds","q","j","sectors","sectorify","sleuth_fat","sector_list","make_sector_list","name","ENDOFCHAIN","files","Paths","FileIndex","FullPaths","FullPathDir","read_directory","build_full_paths","root_name","shift","find_path","make_find_path","raw","find","HEADER_SIGNATURE","HEADER_CLSID","nsectors","Math","ceil","FI","FPD","FP","L","R","C","pl","dad","UCFullPaths","UCPaths","toUpperCase","path","k","UCPath","w","cnt","sector","get_sector_list","start","chkd","sl","buf","buf_chain","modulus","jj","addr","floor","nodes","data","minifat_store","namelen","color","clsid","state","ctime","ct","read_date","mtime","mt","storage","undefined","content","MSSZ","offset","Date","pow","fs","readFileSync","filename","require","readSync","consts","MAXREGSECT","DIFSECT","FATSECT","FREESECT","HEADER_MINOR_VERSION","MAXREGSID","NOSTREAM","EntryTypes","read","utils","module","DO_NOT_EXPORT_CFB"],"mappings":"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","file":"dist/cfb.min.js"} \ No newline at end of file diff --git a/dist/xlscfb.js b/dist/xlscfb.js index 5d937bc..a4b30e2 100644 --- a/dist/xlscfb.js +++ b/dist/xlscfb.js @@ -6,8 +6,8 @@ var DO_NOT_EXPORT_CFB = true; /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '0.11.0'; -function parse(file) { +exports.version = '0.12.0'; +function parse(file, options) { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -27,7 +27,7 @@ var mv = check_get_mver(blob); mver = mv[0]; switch(mver) { case 3: ssz = 512; break; case 4: ssz = 4096; break; - default: throw "Major Version: Expected 3 or 4 saw " + mver; + default: throw new Error("Major Version: Expected 3 or 4 saw " + mver); } /* reprocess header */ @@ -39,7 +39,7 @@ check_shifts(blob, mver); // Number of Directory Sectors var nds = blob.read_shift(4, 'i'); -if(mver === 3 && nds !== 0) throw '# Directory Sectors: Expected 0 saw ' + nds; +if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds); // Number of FAT Sectors //var nfs = blob.read_shift(4, 'i'); @@ -67,7 +67,7 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; @@ -94,7 +94,6 @@ read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); 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) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); @@ -125,13 +124,14 @@ function check_shifts(blob, mver) { var shift = 0x09; // Byte Order - blob.chk('feff', 'Byte Order: '); + //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff + blob.l += 2; // Sector Shift switch((shift = blob.read_shift(2))) { - case 0x09: if(mver !== 3) throw 'MajorVersion/SectorShift Mismatch'; break; - case 0x0c: if(mver !== 4) throw 'MajorVersion/SectorShift Mismatch'; break; - default: throw 'Sector Shift: Expected 9 or 12 saw ' + shift; + case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break; + case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break; + default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift); } // Mini Sector Shift @@ -144,7 +144,7 @@ function check_shifts(blob, mver) { /** Break the file up into sectors */ function sectorify(file, ssz) { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + 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); return sectors; @@ -153,7 +153,7 @@ function sectorify(file, ssz) { /* [MS-CFB] 2.6.4 Red-Black Tree */ function build_full_paths(FI, FPD, FP, Paths) { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad = [], q = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -193,12 +193,12 @@ function build_full_paths(FI, FPD, FP, Paths) { /* [MS-CFB] 2.6.4 */ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; + var UCFullPaths = []; + var UCPaths = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); return function find_path(path) { - var k; + var k = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); @@ -211,9 +211,9 @@ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { /** 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, sectors, ssz, fat_addrs) { - var q; + var q = ENDOFCHAIN; if(idx === ENDOFCHAIN) { - if(cnt !== 0) throw "DIFAT chain shorter than expected"; + if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { var sector = sectors[idx], m = (ssz>>>2)-1; if(!sector) return; @@ -228,18 +228,16 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { /** Follow the linked list of sectors for a given starting point */ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf = [], buf_chain = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; buf_chain.push(sectors[j]); var addr = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); - if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz; + if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } @@ -248,13 +246,13 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { /** Chase down the sector linked lists */ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; + var sl = sectors.length, sector_list = ([]); + var chkd = [], buf = [], buf_chain = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; @@ -262,29 +260,28 @@ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { buf_chain.push(sectors[j]); var addr = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); - if(ssz < 4 + jj) throw "FAT boundary crossed: " + j + " 4 "+ssz; + if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}); } return sector_list; } /* [MS-CFB] 2.6.1 Compound File Directory Entry */ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob = sector.slice(i, i+128); prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -292,16 +289,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 }); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -312,12 +307,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)); prep_blob(o.content, 0); } } @@ -332,17 +327,17 @@ function read_date(blob, offset) { var fs; function readFileSync(filename, options) { - if(fs === undefined) fs = require('fs'); + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } function readSync(blob, options) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { + switch(options && options.type || "base64") { case "file": return readFileSync(blob, options); case "base64": return parse(s2a(Base64.decode(blob)), options); case "binary": return parse(s2a(blob), options); } - return parse(blob); + return parse(blob, options); } /** CFB Constants */ diff --git a/misc/cfb.d.ts b/misc/cfb.d.ts deleted file mode 100644 index 3a46614..0000000 --- a/misc/cfb.d.ts +++ /dev/null @@ -1,104 +0,0 @@ -declare enum CFBEntryType { unknown, storage, stream, lockbytes, property, root } -declare enum CFBStorageType { fat, minifat } - -/* CFB Entry Object demanded by write functions */ -interface CFBEntryMin { - - /* Raw Content (Buffer when available, Array of bytes otherwise) */ - content:any; -} - -/* CFB Entry Object returned by parse functions */ -interface CFBEntry extends CFBEntryMin { - - /* Case-sensitive internal name */ - name:string; - - /* CFB type (salient types: stream, storage) -- see CFBEntryType */ - type:string; - - /* Creation Time */ - ct:Date; - /* Modification Time */ - mt:Date; - - - /* Raw creation time -- see [MS-DTYP] 2.3.3 FILETIME */ - mtime:string; - /* Raw modification time -- see [MS-DTYP] 2.3.3 FILETIME */ - ctime:string; - - /* RBT color: 0 = red, 1 = black */ - color:number; - - /* Class ID represented as hex string */ - clsid:string; - - /* User-Defined State Bits */ - state:number; - - /* Starting Sector */ - start:number; - - /* Data Size */ - size:number; - - /* Storage location -- see CFBStorageType */ - storage:string; -} - - -/* cfb.FullPathDir as demanded by write functions */ -interface CFBDirectoryMin { - - /* keys are unix-style paths */ - [key:string]: CFBEntryMin; -} - -/* cfb.FullPathDir Directory object */ -interface CFBDirectory extends CFBDirectoryMin { - - /* cfb.FullPathDir keys are paths; cfb.Directory keys are file names */ - [key:string]: CFBEntry; -} - - -/* cfb object demanded by write functions */ -interface CFBContainerMin { - - /* Path -> CFB object mapping */ - FullPathDir:CFBDirectoryMin; -} - -/* cfb object returned by read and parse functions */ -interface CFBContainer extends CFBContainerMin { - - /* search by path or file name */ - find(string):CFBEntry; - - /* list of streams and storages */ - FullPaths:string[]; - - /* Path -> CFB object mapping */ - FullPathDir:CFBDirectory; - - /* Array of entries in the same order as FullPaths */ - FileIndex:CFBEntry[]; - - /* Raw Content, in chunks (Buffer when available, Array of bytes otherwise) */ - raw:any[]; -} - - -interface CFB { - read(f:any, options:any):CFBContainer; - parse(f:any):CFBContainer; - utils: { - ReadShift(size:any,t?:any):any; - WarnField(hexstr:string,fld?:string); - CheckField(hexstr:string,fld?:string); - prep_blob(blob:any, pos?:number):any; - bconcat(bufs:any[]):any; - }; - main; -} diff --git a/misc/cfb_.ts b/misc/cfb_.ts deleted file mode 100755 index fb2f630..0000000 --- a/misc/cfb_.ts +++ /dev/null @@ -1,35 +0,0 @@ -/// -/// - -/* vim: set ts=2: */ - -var CFB = require('../cfb'); -var fs = require('fs'), program = require('commander'); -program - .version('0.8.1') - .usage('[options] ') - .option('-q, --quiet', 'print but do not extract') - .parse(process.argv); - -if(program.args.length === 0 || !fs.existsSync(program.args[0])) { - console.error("Usage: " + process.argv[1] + " [-q] "); - process.exit(1); -} - -var cfb = CFB.read(program.args[0], {type:'file'}); -if(program.quiet) { - console.log("Full Paths:") - console.log(cfb.FullPaths.map(function(x) { return " " + x; }).join("\n")); - console.log("Full Path Directory:") - console.log(cfb.FullPathDir); - return; -} -for(var i=0; i != cfb.FullPaths.length; ++i) { - if(cfb.FullPaths[i].slice(-1) === "/") { - console.error("mkdir " + cfb.FullPaths[i]); - fs.mkdirSync(cfb.FullPaths[i]); - } else { - console.error("writing " + cfb.FullPaths[i]); - fs.writeFileSync(cfb.FullPaths[i], cfb.FileIndex[i].content); - } -} diff --git a/misc/flow.js b/misc/flow.js index f9a5c9f..ef99213 100644 --- a/misc/flow.js +++ b/misc/flow.js @@ -1,5 +1,89 @@ /*:: -type CFBModule = any; +type CFBModule = { + version:string; + read:(blob:RawBytes|string, opts:CFBReadOpts)=>CFBContainer; + parse:(file:RawBytes, opts:CFBReadOpts)=>CFBContainer; + utils:CFBUtils; +}; +type CFBFullPathDir = { + [n:string]: CFBEntry; +} + +type CFBUtils = any; + +type ReadShiftFunc = { + //(size:number, t:?string):number|string; + (size:16):string; + (size:1|2|4, t:?string):number; +}; +type CheckFieldFunc = {(hexstr:string, fld:string):void;}; + +type RawBytes = Array | Buffer | Uint8Array; + +class CFBlobArray extends Array { + l:number; + read_shift:ReadShiftFunc; + chk:CheckFieldFunc; +}; +interface CFBlobBuffer extends Buffer { + l:number; + slice:(start:number, end:?number)=>Buffer; + read_shift:ReadShiftFunc; + chk:CheckFieldFunc; +}; +interface CFBlobUint8 extends Uint8Array { + l:number; + slice:(start:number, end:?number)=>Uint8Array; + read_shift:ReadShiftFunc; + chk:CheckFieldFunc; +}; + +interface CFBlobber { + [n:number]:number; + l:number; + length:number; + slice:(start:number, end:?number)=>RawBytes; + read_shift:ReadShiftFunc; + chk:CheckFieldFunc; +}; + +type CFBlob = CFBlobArray | CFBlobBuffer | CFBlobUint8; + +interface CFBReadOpts { + type:?string; +}; + +type CFBFileIndex = Array; + +type CFBFindPath = (n:string)=>?CFBEntry; + +type CFBContainer = { + raw:{ + header:any; + sectors:Array; + }; + FileIndex:CFBFileIndex; + FullPathDir:CFBDirectory; + FullPaths:Array; + find:CFBFindPath; +} + +type CFBEntry = { + name: string; + type: number; + ct?: Date; + mt?: Date; + color: number; + clsid: string; + state: number; + start: number; + size: number; + storage?: "fat" | "minifat"; + L: number; + R: number; + C: number; + content?: CFBlob; +} */ diff --git a/misc/node.d.ts b/misc/node.d.ts deleted file mode 100644 index 18156c5..0000000 --- a/misc/node.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -declare var require: { - (id: string): any; -} - -declare var process: { - argv: string[]; - exit(status: number): void; -} diff --git a/package.json b/package.json index 0cfafb4..8291027 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cfb", - "version": "0.11.1", + "version": "0.12.0", "author": "sheetjs", "description": "Compound File Binary File Format extractor", "keywords": [ "cfb", "compression", "office" ], @@ -8,32 +8,37 @@ "cfb": "./bin/cfb.njs" }, "main": "./cfb", - "files": [ - "LICENSE", - "README.md", - "bin/", - "dist/", - "cfb.js", - "xlscfb.flow.js" - ], + "types": "types", + "browser": { + "node": false, + "process": false, + "fs": false + }, "dependencies": { - "commander":"" + "commander":"~2.11.0" }, "devDependencies": { - "mocha":"", - "xlsjs":"", - "uglify-js":"" + "mocha":"~2.5.3", + "blanket": "~1.2.3", + "@sheetjs/uglify-js":"~2.7.3", + "@types/node":"^8.0.7", + "@types/commander":"^2.9.0", + "dtslint": "^0.1.2", + "typescript": "2.2.0" }, "repository": { "type":"git", "url":"git://github.com/SheetJS/js-cfb.git" }, "scripts": { "pretest": "make init", - "test": "make test" + "test": "make test", + "dtslint": "dtslint types" }, "config": { "blanket": { "pattern": "cfb.js" } }, + "files": [ "LICENSE", "README.md", "bin/", "dist/", "types/index.d.ts", "types/tsconfig.json", "cfb.js", "xlscfb.flow.js" ], + "homepage": "http://sheetjs.com/opensource", "bugs": { "url": "https://github.com/SheetJS/js-cfb/issues" }, "license": "Apache-2.0", "engines": { "node": ">=0.8" } diff --git a/types/bin_cfb.ts b/types/bin_cfb.ts new file mode 100755 index 0000000..ec7855a --- /dev/null +++ b/types/bin_cfb.ts @@ -0,0 +1,35 @@ +/* vim: set ts=2: */ +import * as CFB from 'cfb'; +import fs = require('fs'); +import program = require('commander'); +program + .version(CFB.version) + .usage('[options] ') + .option('-q, --quiet', 'process but do not report') + .option('-d, --dump', 'dump internal representation but do not extract') + .parse(process.argv); + +if(program.args.length === 0 || !fs.existsSync(program.args[0])) { + console.error("Usage: " + process.argv[1] + " [-q] "); + process.exit(1); +} + +const opts: CFB.CFBParsingOptions = {type:'file'}; + +const cfb: CFB.CFBContainer = CFB.read(program.args[0], opts); + +if(program.dump) { + console.log("Full Paths:"); + console.log(cfb.FullPaths.map((x) => " " + x).join("\n")); + console.log("Full Path Directory:"); + console.log(cfb.FullPathDir); +} +if(!program.quiet && !program.dump) for(let i=0; i!==cfb.FullPaths.length; ++i) { + if(cfb.FullPaths[i].slice(-1) === "/") { + console.error("mkdir " + cfb.FullPaths[i]); + fs.mkdirSync(cfb.FullPaths[i]); + } else { + console.error("writing " + cfb.FullPaths[i]); + fs.writeFileSync(cfb.FullPaths[i], cfb.FileIndex[i].content); + } +} diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..2d2255d --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,100 @@ +/* index.d.ts (C) 2013-present SheetJS */ +// TypeScript Version: 2.2 + +/** Version string */ +export const version: string; + +/** Parse a buffer or array */ +export function parse(f: CFB$Blob, options?: CFBParsingOptions): CFBContainer; + +/** Read a blob or file or binary string */ +export function read(f: CFB$Blob | string, options?: CFBParsingOptions): CFBContainer; + +/** Utility functions */ +export const utils: CFB$Utils; + + +/** Options for read and readFile */ +export interface CFBParsingOptions { + /** Input data encoding */ + type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array'; +} + +export type CFB$Blob = Buffer | number[] | Uint8Array; + +export enum CFBEntryType { unknown, storage, stream, lockbytes, property, root } +export enum CFBStorageType { fat, minifat } + +/** CFB File Entry Object */ +export interface CFBEntry { + /** Case-sensitive internal name */ + name: string; + + /** CFB type (salient types: stream, storage) -- see CFBEntryType */ + type: number; + + /** Raw Content (Buffer when available, Array of bytes otherwise) */ + content: CFB$Blob; + + /** Creation Time */ + ct?: Date; + + /** Modification Time */ + mt?: Date; + + /** Red/Black Tree color: 0 = red, 1 = black */ + color: number; + + /** Class ID represented as hex string */ + clsid: string; + + /** User-Defined State Bits */ + state: number; + + /** Starting Sector */ + start: number; + + /** Data Size */ + size: number; + + /** Storage location -- see CFBStorageType */ + storage?: string; +} + + +/* cfb.FullPathDir Directory object */ +export interface CFBDirectory { + /* cfb.FullPathDir keys are paths; cfb.Directory keys are file names */ + [key: string]: CFBEntry; +} + + +/* File object */ +export interface CFBContainer { + /* search by path or file name */ + find(name: string): CFBEntry; + + /* list of streams and storages */ + FullPaths: string[]; + + /* Path -> CFB object mapping */ + FullPathDir: CFBDirectory; + + /* Array of entries in the same order as FullPaths */ + FileIndex: CFBEntry[]; + + /* Raw Content, in chunks (Buffer when available, Array of bytes otherwise) */ + raw: { + header: CFB$Blob, + sectors: CFB$Blob[]; + }; +} + +/** General utilities */ +export interface CFB$Utils { + ReadShift(size: number, t?: string): number|string; + WarnField(hexstr: string, fld?: string): void; + CheckField(hexstr: string, fld?: string): void; + prep_blob(blob: any, pos?: number): CFB$Blob; + bconcat(bufs: any[]): any; +} diff --git a/types/tsconfig.json b/types/tsconfig.json new file mode 100644 index 0000000..2b6ed3c --- /dev/null +++ b/types/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ "es5" ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": false, + "baseUrl": ".", + "paths": { "cfb": ["."] }, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + } +} diff --git a/types/tslint.json b/types/tslint.json new file mode 100644 index 0000000..d9401a9 --- /dev/null +++ b/types/tslint.json @@ -0,0 +1,11 @@ +{ + "extends": "dtslint/dtslint.json", + "rules": { + "whitespace": false, + "no-sparse-arrays": false, + "only-arrow-functions": false, + "no-consecutive-blank-lines": false, + "prefer-conditional-expression": false, + "one-variable-per-declaration": false + } +} diff --git a/xlscfb.flow.js b/xlscfb.flow.js index c5b75e1..22ba520 100644 --- a/xlscfb.flow.js +++ b/xlscfb.flow.js @@ -18,20 +18,25 @@ declare var chr1:any; /*jshint eqnull:true */ /*:: -declare var DO_NOT_EXPORT_CFB:any; -type SectorEntry = any; +declare var DO_NOT_EXPORT_CFB:?boolean; +type SectorEntry = { + name?:string; + nodes?:Array; + data:RawBytes; +}; type SectorList = { - (k:string|number):SectorEntry; + [k:string|number]:SectorEntry; name:?string; - fat_addrs:any; + fat_addrs:Array; ssz:number; } +type CFBFiles = {[n:string]:CFBEntry}; */ /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ -var exports = {}; -exports.version = '0.11.1'; -function parse(file) { +var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; +exports.version = '0.12.0'; +function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -40,10 +45,10 @@ var dir_start = 0; // first directory sector location var minifat_start = 0; // first mini FAT sector location var difat_start = 0; // first mini FAT sector location -var fat_addrs = []; // locations of FAT sectors +var fat_addrs/*:Array*/ = []; // locations of FAT sectors /* [MS-CFB] 2.2 Compound File Header */ -var blob/*:any*/ = file.slice(0,512); +var blob/*:CFBlob*/ = /*::(*/file.slice(0,512)/*:: :any)*/; prep_blob(blob, 0); /* major version */ @@ -55,14 +60,14 @@ switch(mver) { } /* reprocess header */ -if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); } +if(ssz !== 512) { blob = /*::(*/file.slice(0,ssz)/*:: :any)*/; prep_blob(blob, 28 /* blob.l */); } /* Save header for final object */ -var header = file.slice(0,ssz); +var header/*:RawBytes*/ = file.slice(0,ssz); check_shifts(blob, mver); // Number of Directory Sectors -var nds = blob.read_shift(4, 'i'); +var nds/*:number*/ = blob.read_shift(4, 'i'); if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds); // Number of FAT Sectors @@ -91,14 +96,14 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; } /** Break the file up into sectors */ -var sectors = sectorify(file, ssz); +var sectors/*:Array*/ = sectorify(file, ssz); sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs); @@ -112,13 +117,12 @@ sector_list.fat_addrs = fat_addrs; sector_list.ssz = ssz; /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -var files = {}, Paths/*:any*/ = [], FileIndex = [], FullPaths = [], FullPathDir = {}; +var files/*:CFBFiles*/ = {}, Paths/*:Array*/ = [], FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array*/ = [], FullPathDir = {}; read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); build_full_paths(FileIndex, FullPathDir, FullPaths, Paths); -var root_name = Paths.shift(); -Paths.root = root_name; +var root_name/*:string*/ = Paths.shift(); /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); @@ -133,7 +137,7 @@ return { } // parse /* [MS-CFB] 2.2 Compound File Header -- read up to major version */ -function check_get_mver(blob) { +function check_get_mver(blob/*:CFBlob*/)/*:[number, number]*/ { // header signature 8 blob.chk(HEADER_SIGNATURE, 'Header Signature: '); @@ -141,11 +145,11 @@ function check_get_mver(blob) { blob.chk(HEADER_CLSID, 'CLSID: '); // minor version 2 - var mver = blob.read_shift(2, 'u'); + var mver/*:number*/ = blob.read_shift(2, 'u'); return [blob.read_shift(2,'u'), mver]; } -function check_shifts(blob, mver) { +function check_shifts(blob/*:CFBlob*/, mver/*:number*/)/*:void*/ { var shift = 0x09; // Byte Order @@ -167,18 +171,18 @@ function check_shifts(blob, mver) { } /** Break the file up into sectors */ -function sectorify(file, ssz) { +function sectorify(file/*:RawBytes*/, ssz/*:number*/)/*:Array*/ { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + var sectors/*:Array*/ = []; for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz); sectors[nsectors-1] = file.slice(nsectors*ssz); return sectors; } /* [MS-CFB] 2.6.4 Red-Black Tree */ -function build_full_paths(FI, FPD, FP, Paths) { +function build_full_paths(FI/*:CFBFileIndex*/, FPD/*:CFBFullPathDir*/, FP/*:Array*/, Paths/*:Array*/)/*:void*/ { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad/*:Array*/ = [], q/*:Array*/ = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -217,17 +221,17 @@ function build_full_paths(FI, FPD, FP, Paths) { } /* [MS-CFB] 2.6.4 */ -function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; +function make_find_path(FullPaths/*:Array*/, Paths/*:Array*/, FileIndex/*:CFBFileIndex*/, files/*:CFBFiles*/, root_name/*:string*/)/*:CFBFindPath*/ { + var UCFullPaths/*:Array*/ = []; + var UCPaths/*:Array*/ = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); - return function find_path(path/*:string*/) { - var k; + return function find_path(path/*:string*/)/*:?CFBEntry*/ { + var k/*:boolean*/ = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; - var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); - var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); + var UCPath/*:string*/ = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); + var w/*:number*/ = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); if(w === -1) return null; return k === true ? FileIndex[w] : files[Paths[w]]; }; @@ -235,8 +239,8 @@ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { /** 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, sectors, ssz, fat_addrs) { - var q; +function sleuth_fat(idx/*:number*/, cnt/*:number*/, sectors/*:Array*/, ssz/*:number*/, fat_addrs)/*:void*/ { + var q/*:number*/ = ENDOFCHAIN; if(idx === ENDOFCHAIN) { if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { @@ -251,13 +255,11 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { } /** Follow the linked list of sectors for a given starting point */ -function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { +function get_sector_list(sectors/*:Array*/, start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/, chkd/*:?Array*/)/*:SectorEntry*/ { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf/*:Array*/ = [], buf_chain/*:Array*/ = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; @@ -272,44 +274,43 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { } /** Chase down the sector linked lists */ -function make_sector_list(sectors, dir_start, fat_addrs, ssz/*:number*/)/*:any*/ { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; +function make_sector_list(sectors/*:Array*/, dir_start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/)/*:SectorList*/ { + var sl = sectors.length, sector_list/*:SectorList*/ = ([]/*:any*/); + var chkd/*:Array*/ = [], buf/*:Array*/ = [], buf_chain/*:Array*/ = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]/*:Array*/); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; buf[buf.length] = j; buf_chain.push(sectors[j]); - var addr = fat_addrs[Math.floor(j*4/ssz)]; + var addr/*:number*/ = fat_addrs[Math.floor(j*4/ssz)]; jj = ((j*4) & modulus); if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}/*:SectorEntry*/); } return sector_list; } /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; +function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sectors/*:Array*/, Paths/*:Array*/, nmfs, files, FileIndex) { var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob/*:CFBlob*/ = /*::(*/sector.slice(i, i+128)/*:: :any)*/; prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o/*:CFBEntry*/ = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -317,16 +318,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') - }/*:any*/); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 + }); + var ctime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime/*:number*/ = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -337,12 +336,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)/*:any*/); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)/*:any*/); prep_blob(o.content, 0); } } @@ -351,23 +350,23 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil } } -function read_date(blob, offset) { +function read_date(blob/*:RawBytes|CFBlob*/, offset/*:number*/)/*:Date*/ { return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000); } -var fs; -function readFileSync(filename/*:string*/, options/*:any*/) { - if(fs === undefined) fs = require('fs'); +var fs/*:: = require('fs'); */; +function readFileSync(filename/*:string*/, options/*:CFBReadOpts*/) { + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } -function readSync(blob/*:any*/, options/*:any*/) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { - case "file": return readFileSync(blob, options); - case "base64": return parse(s2a(Base64.decode(blob)), options); - case "binary": return parse(s2a(blob), options); +function readSync(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) { + switch(options && options.type || "base64") { + case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return readFileSync(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(blob); + return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options); } /** CFB Constants */ diff --git a/xlscfb.js b/xlscfb.js index 5259536..a4b30e2 100644 --- a/xlscfb.js +++ b/xlscfb.js @@ -6,8 +6,8 @@ var DO_NOT_EXPORT_CFB = true; /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '0.11.1'; -function parse(file) { +exports.version = '0.12.0'; +function parse(file, options) { var mver = 3; // major version var ssz = 512; // sector size var nmfs = 0; // number of mini FAT sectors @@ -67,7 +67,7 @@ difat_start = blob.read_shift(4, 'i'); ndfs = blob.read_shift(4, 'i'); // Grab FAT Sector Locations -for(var q, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ +for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ q = blob.read_shift(4, 'i'); if(q<0) break; fat_addrs[j] = q; @@ -94,7 +94,6 @@ read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex); 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) */ var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name); @@ -145,7 +144,7 @@ function check_shifts(blob, mver) { /** Break the file up into sectors */ function sectorify(file, ssz) { var nsectors = Math.ceil(file.length/ssz)-1; - var sectors = new Array(nsectors); + 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); return sectors; @@ -154,7 +153,7 @@ function sectorify(file, ssz) { /* [MS-CFB] 2.6.4 Red-Black Tree */ function build_full_paths(FI, FPD, FP, Paths) { var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; - var dad = new Array(pl), q = new Array(pl); + var dad = [], q = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -194,12 +193,12 @@ function build_full_paths(FI, FPD, FP, Paths) { /* [MS-CFB] 2.6.4 */ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { - var UCFullPaths = new Array(FullPaths.length); - var UCPaths = new Array(Paths.length), i; + var UCFullPaths = []; + var UCPaths = [], i = 0; for(i = 0; i < FullPaths.length; ++i) UCFullPaths[i] = FullPaths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); for(i = 0; i < Paths.length; ++i) UCPaths[i] = Paths[i].toUpperCase().replace(chr0,'').replace(chr1,'!'); return function find_path(path) { - var k; + var k = false; if(path.charCodeAt(0) === 47 /* "/" */) { k=true; path = root_name + path; } else k = path.indexOf("/") !== -1; var UCPath = path.toUpperCase().replace(chr0,'').replace(chr1,'!'); @@ -212,7 +211,7 @@ function make_find_path(FullPaths, Paths, FileIndex, files, root_name) { /** 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, sectors, ssz, fat_addrs) { - var q; + var q = ENDOFCHAIN; if(idx === ENDOFCHAIN) { if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); } else if(idx !== -1 /*FREESECT*/) { @@ -229,11 +228,9 @@ function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { /** Follow the linked list of sectors for a given starting point */ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { var sl = sectors.length; - var buf, buf_chain; - if(!chkd) chkd = new Array(sl); - var modulus = ssz - 1, j, jj; - buf = []; - buf_chain = []; + var buf = [], buf_chain = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { chkd[j] = true; buf[buf.length] = j; @@ -249,13 +246,13 @@ function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { /** Chase down the sector linked lists */ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { - var sl = sectors.length, sector_list = new Array(sl); - var chkd = new Array(sl), buf, buf_chain; - var modulus = ssz - 1, i, j, k, jj; + var sl = sectors.length, sector_list = ([]); + var chkd = [], buf = [], buf_chain = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; for(i=0; i < sl; ++i) { - buf = []; + buf = ([]); k = (i + dir_start); if(k >= sl) k-=sl; - if(chkd[k] === true) continue; + if(chkd[k]) continue; buf_chain = []; for(j=k; j>=0;) { chkd[j] = true; @@ -267,25 +264,24 @@ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { if(!sectors[addr]) break; j = __readInt32LE(sectors[addr], jj); } - sector_list[k] = {nodes: buf, data:__toBuffer([buf_chain])}; + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}); } return sector_list; } /* [MS-CFB] 2.6.1 Compound File Directory Entry */ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex) { - var blob; var minifat_store = 0, pl = (Paths.length?2:0); var sector = sector_list[dir_start].data; - var i = 0, namelen = 0, name, o, ctime, mtime; + var i = 0, namelen = 0, name; for(; i < sector.length; i+= 128) { - blob = sector.slice(i, i+128); + var blob = sector.slice(i, i+128); prep_blob(blob, 64); namelen = blob.read_shift(2); if(namelen === 0) continue; name = __utf16le(blob,0,namelen-pl); Paths.push(name); - o = ({ + var o = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -293,16 +289,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil R: blob.read_shift(4, 'i'), C: blob.read_shift(4, 'i'), clsid: blob.read_shift(16), - state: blob.read_shift(4, 'i') + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 }); - ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(ctime !== 0) { - o.ctime = ctime; o.ct = read_date(blob, blob.l-8); - } - mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); - if(mtime !== 0) { - o.mtime = mtime; o.mt = read_date(blob, blob.l-8); - } + var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); o.start = blob.read_shift(4, 'i'); o.size = blob.read_shift(4, 'i'); if(o.type === 5) { /* root */ @@ -313,12 +307,12 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil o.storage = 'fat'; if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); sector_list[o.start].name = o.name; - o.content = sector_list[o.start].data.slice(0,o.size); + o.content = (sector_list[o.start].data.slice(0,o.size)); prep_blob(o.content, 0); } else { o.storage = 'minifat'; if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN) { - o.content = sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size); + o.content = (sector_list[minifat_store].data.slice(o.start*MSSZ,o.start*MSSZ+o.size)); prep_blob(o.content, 0); } } @@ -333,17 +327,17 @@ function read_date(blob, offset) { var fs; function readFileSync(filename, options) { - if(fs === undefined) fs = require('fs'); + if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } function readSync(blob, options) { - switch(options !== undefined && options.type !== undefined ? options.type : "base64") { + switch(options && options.type || "base64") { case "file": return readFileSync(blob, options); case "base64": return parse(s2a(Base64.decode(blob)), options); case "binary": return parse(s2a(blob), options); } - return parse(blob); + return parse(blob, options); } /** CFB Constants */