From 3fd73f806bf9f9327b9052613a5a669792645088 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Wed, 20 Sep 2017 19:33:03 -0400 Subject: [PATCH] version bump 0.13.1: determinism - pin unknown dates and zero-fill end of file - cfb_add can take an absolute path e.g. "/Workbook" --- Makefile | 5 +- bits/31_version.js | 2 +- bits/56_dirtree.js | 2 +- bits/68_mini.js | 2 +- bits/85_api.js | 8 +- cfb.flow.js | 14 ++- cfb.js | 14 ++- dist/cfb.js | 14 ++- dist/cfb.min.js | 2 +- dist/cfb.min.map | 2 +- dist/xlscfb.js | 272 +++++++++++++++++++++------------------------ index.html | 142 ++++++++++++++--------- package.json | 2 +- test.js | 18 +-- xlscfb.flow.js | 75 ++----------- xlscfb.js | 75 ++----------- 16 files changed, 283 insertions(+), 366 deletions(-) diff --git a/Makefile b/Makefile index bc69d3e..1a65142 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ dist: dist-deps $(TARGET) ## Prepare JS files for distribution .PHONY: dist-deps dist-deps: xlscfb.js ## Copy dependencies for distribution - cp xlscfb.js dist/xlscfb.js + cp xlscfb.flow.js dist/xlscfb.js .PHONY: aux aux: $(AUXTARGETS) @@ -61,7 +61,8 @@ aux: $(AUXTARGETS) .PHONY: xls xls: xlscfb.js -XLSDEPS=misc/suppress_export.js $(filter-out bits/08_blob.js,$(DEPS)) +XLSSKIP=bits/08_blob.js bits/04_base64.js bits/05_buf.js +XLSDEPS=misc/suppress_export.js $(filter-out $(XLSSKIP),$(DEPS)) xlscfb.flow.js: $(XLSDEPS) ## Build support library cat $^ | tr -d '\15\32' > $@ diff --git a/bits/31_version.js b/bits/31_version.js index 026922b..29e2371 100644 --- a/bits/31_version.js +++ b/bits/31_version.js @@ -1 +1 @@ -exports.version = '0.13.0'; +exports.version = '0.13.1'; diff --git a/bits/56_dirtree.js b/bits/56_dirtree.js index c14462b..4a1a093 100644 --- a/bits/56_dirtree.js +++ b/bits/56_dirtree.js @@ -1,4 +1,4 @@ - var now = new Date(), j = 0; + var now = new Date(1987, 1, 19), j = 0; var data/*:Array<[string, CFBEntry]>*/ = []; for(i = 0; i < cfb.FullPaths.length; ++i) { if(cfb.FileIndex[i].type === 0) continue; diff --git a/bits/68_mini.js b/bits/68_mini.js index faf920c..9b080b2 100644 --- a/bits/68_mini.js +++ b/bits/68_mini.js @@ -6,4 +6,4 @@ for(; j & 0x3F; ++j) o.write_shift(1, 0); } } - + while(o.l < o.length) o.write_shift(1, 0); diff --git a/bits/85_api.js b/bits/85_api.js index 8f449c0..da077e4 100644 --- a/bits/85_api.js +++ b/bits/85_api.js @@ -8,9 +8,15 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o init_cfb(cfb); var file = CFB.find(cfb, name); if(!file) { + var fpath = cfb.FullPaths[0]; + if(name.slice(0, fpath.length) == fpath) fpath = name; + else { + if(fpath.slice(-1) != "/") fpath += "/"; + fpath = (fpath + name).replace("//","/"); + } file = ({name: filename(name)}/*:any*/); cfb.FileIndex.push(file); - cfb.FullPaths.push(name); + cfb.FullPaths.push(fpath); CFB.utils.cfb_gc(cfb); } /*:: if(!file) throw new Error("unreachable"); */ diff --git a/cfb.flow.js b/cfb.flow.js index c4e9a01..317aa94 100644 --- a/cfb.flow.js +++ b/cfb.flow.js @@ -179,7 +179,7 @@ type CFBFiles = {[n:string]:CFBEntry}; /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; -exports.version = '0.13.0'; +exports.version = '0.13.1'; /* [MS-CFB] 2.6.4 */ function namecmp(l/*:string*/, r/*:string*/)/*:number*/ { var L = l.split("/"), R = r.split("/"); @@ -552,7 +552,7 @@ function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ { } if(!gc && !f) return; - var now = new Date(), j = 0; + var now = new Date(1987, 1, 19), j = 0; var data/*:Array<[string, CFBEntry]>*/ = []; for(i = 0; i < cfb.FullPaths.length; ++i) { if(cfb.FileIndex[i].type === 0) continue; @@ -730,7 +730,7 @@ function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ { for(; j & 0x3F; ++j) o.write_shift(1, 0); } } - + while(o.l < o.length) o.write_shift(1, 0); return o; } /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ @@ -809,9 +809,15 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o init_cfb(cfb); var file = CFB.find(cfb, name); if(!file) { + var fpath = cfb.FullPaths[0]; + if(name.slice(0, fpath.length) == fpath) fpath = name; + else { + if(fpath.slice(-1) != "/") fpath += "/"; + fpath = (fpath + name).replace("//","/"); + } file = ({name: filename(name)}/*:any*/); cfb.FileIndex.push(file); - cfb.FullPaths.push(name); + cfb.FullPaths.push(fpath); CFB.utils.cfb_gc(cfb); } /*:: if(!file) throw new Error("unreachable"); */ diff --git a/cfb.js b/cfb.js index 85629d5..f292341 100644 --- a/cfb.js +++ b/cfb.js @@ -161,7 +161,7 @@ function new_buf(sz) { /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '0.13.0'; +exports.version = '0.13.1'; /* [MS-CFB] 2.6.4 */ function namecmp(l, r) { var L = l.split("/"), R = r.split("/"); @@ -534,7 +534,7 @@ function rebuild_cfb(cfb, f) { } if(!gc && !f) return; - var now = new Date(), j = 0; + var now = new Date(1987, 1, 19), j = 0; var data = []; for(i = 0; i < cfb.FullPaths.length; ++i) { if(cfb.FileIndex[i].type === 0) continue; @@ -707,7 +707,7 @@ if(file.size > 0 && file.size < 0x1000) { for(; j & 0x3F; ++j) o.write_shift(1, 0); } } - + while(o.l < o.length) o.write_shift(1, 0); return o; } /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ @@ -785,9 +785,15 @@ function cfb_add(cfb, name, content, opts) { init_cfb(cfb); var file = CFB.find(cfb, name); if(!file) { + var fpath = cfb.FullPaths[0]; + if(name.slice(0, fpath.length) == fpath) fpath = name; + else { + if(fpath.slice(-1) != "/") fpath += "/"; + fpath = (fpath + name).replace("//","/"); + } file = ({name: filename(name)}); cfb.FileIndex.push(file); - cfb.FullPaths.push(name); + cfb.FullPaths.push(fpath); CFB.utils.cfb_gc(cfb); } file.content = (content); diff --git a/dist/cfb.js b/dist/cfb.js index 85629d5..f292341 100644 --- a/dist/cfb.js +++ b/dist/cfb.js @@ -161,7 +161,7 @@ function new_buf(sz) { /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '0.13.0'; +exports.version = '0.13.1'; /* [MS-CFB] 2.6.4 */ function namecmp(l, r) { var L = l.split("/"), R = r.split("/"); @@ -534,7 +534,7 @@ function rebuild_cfb(cfb, f) { } if(!gc && !f) return; - var now = new Date(), j = 0; + var now = new Date(1987, 1, 19), j = 0; var data = []; for(i = 0; i < cfb.FullPaths.length; ++i) { if(cfb.FileIndex[i].type === 0) continue; @@ -707,7 +707,7 @@ if(file.size > 0 && file.size < 0x1000) { for(; j & 0x3F; ++j) o.write_shift(1, 0); } } - + while(o.l < o.length) o.write_shift(1, 0); return o; } /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ @@ -785,9 +785,15 @@ function cfb_add(cfb, name, content, opts) { init_cfb(cfb); var file = CFB.find(cfb, name); if(!file) { + var fpath = cfb.FullPaths[0]; + if(name.slice(0, fpath.length) == fpath) fpath = name; + else { + if(fpath.slice(-1) != "/") fpath += "/"; + fpath = (fpath + name).replace("//","/"); + } file = ({name: filename(name)}); cfb.FileIndex.push(file); - cfb.FullPaths.push(name); + cfb.FullPaths.push(fpath); CFB.utils.cfb_gc(cfb); } file.content = (content); diff --git a/dist/cfb.min.js b/dist/cfb.min.js index cf950bd..005ea73 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 e(){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";return{encode:function(r){var t="";var i,n,a;var f,s,h,l;for(var o=0;o>2;n=r.charCodeAt(o++);s=(i&3)<<4|n>>4;a=r.charCodeAt(o++);h=(n&15)<<2|a>>6;l=a&63;if(isNaN(n)){h=l=64}else if(isNaN(a)){l=64}t+=e.charAt(f)+e.charAt(s)+e.charAt(h)+e.charAt(l)}return t},decode:function r(t){var i="";var n,a,f;var s,h,l,o;t=t.replace(/[^\w\+\/\=]/g,"");for(var u=0;u>4;i+=String.fromCharCode(n);l=e.indexOf(t.charAt(u++));a=(h&15)<<4|l>>2;if(l!==64){i+=String.fromCharCode(a)}o=e.indexOf(t.charAt(u++));f=(l&3)<<6|o;if(o!==64){i+=String.fromCharCode(f)}}return i}}}();var has_buf=typeof Buffer!=="undefined"&&typeof process!=="undefined"&&typeof process.versions!=="undefined"&&process.versions.node;function new_raw_buf(e){return new(has_buf?Buffer:Array)(e)}var s2a=function r(e){if(has_buf)return new Buffer(e,"binary");return e.split("").map(function(e){return e.charCodeAt(0)&255})};var chr0=/\u0000/g,chr1=/[\u0001-\u0006]/;var __toBuffer=function(e){var r=[];for(var t=0;t0&&Buffer.isBuffer(e[0][0])?Buffer.concat(e[0]):___toBuffer(e)};s2a=function(e){return new Buffer(e,"binary")};bconcat=function(e){return Buffer.isBuffer(e[0])?Buffer.concat(e):__bconcat(e)}}var __readUInt8=function(e,r){return e[r]};var __readUInt16LE=function(e,r){return e[r+1]*(1<<8)+e[r]};var __readInt16LE=function(e,r){var t=e[r+1]*(1<<8)+e[r];return t<32768?t:(65535-t+1)*-1};var __readUInt32LE=function(e,r){return e[r+3]*(1<<24)+(e[r+2]<<16)+(e[r+1]<<8)+e[r]};var __readInt32LE=function(e,r){return(e[r+3]<<24)+(e[r+2]<<16)+(e[r+1]<<8)+e[r]};function ReadShift(e,r){var t,i,n=0;switch(e){case 1:t=__readUInt8(this,this.l);break;case 2:t=(r!=="i"?__readUInt16LE:__readInt16LE)(this,this.l);break;case 4:t=__readInt32LE(this,this.l);break;case 16:n=2;i=__hexlify(this,this.l,e);}this.l+=e;if(n===0)return t;return i}var __writeUInt32LE=function(e,r,t){e[t]=r&255;e[t+1]=r>>>8&255;e[t+2]=r>>>16&255;e[t+3]=r>>>24&255};var __writeInt32LE=function(e,r,t){e[t]=r&255;e[t+1]=r>>8&255;e[t+2]=r>>16&255;e[t+3]=r>>24&255};function WriteShift(e,r,t){var i=0,n=0;switch(t){case"hex":for(;n>8}while(this.l>>=8;this[this.l+1]=r&255;break;case 4:i=4;__writeUInt32LE(this,r,this.l);break;case-4:i=4;__writeInt32LE(this,r,this.l);break;}this.l+=i;return this}function CheckField(e,r){var t=__hexlify(this,this.l,e.length>>1);if(t!==e)throw new Error(r+"Expected "+e+" saw "+t);this.l+=e.length>>1}function prep_blob(e,r){e.l=r;e.read_shift=ReadShift;e.chk=CheckField;e.write_shift=WriteShift}function new_buf(e){var r=new_raw_buf(e);prep_blob(r,0);return r}var CFB=function t(){var e={};e.version="0.13.0";function r(e,r){var t=e.split("/"),i=r.split("/");for(var n=0,a=0,f=Math.min(t.length,i.length);n0&&d!==E)y[d].name="!MiniFAT";y[w[0]].name="!FAT";y.fat_addrs=w;y.ssz=i;var S={},A=[],m=[],B=[],k={};c(_,y,C,A,n,S,m);h(m,k,B,A);A.shift();var L={FileIndex:m,FullPaths:B,FullPathDir:k};if(r&&r.raw)L.raw={header:I,sectors:C};return L}function a(e){e.chk(C,"Header Signature: ");e.chk(S,"CLSID: ");var r=e.read_shift(2,"u");return[e.read_shift(2,"u"),r]}function f(e,r){var t=9;e.l+=2;switch(t=e.read_shift(2)){case 9:if(r!=3)throw new Error("Sector Shift: Expected 9 saw "+t);break;case 12:if(r!=4)throw new Error("Sector Shift: Expected 12 saw "+t);break;default:throw new Error("Sector Shift: Expected 9 or 12 saw "+t);}e.chk("0600","Mini Sector Shift: ");e.chk("000000000000","Reserved: ")}function s(e,r){var t=Math.ceil(e.length/r)-1;var i=[];for(var n=1;n>>2)-1;if(!f)return;for(var h=0;h=0;){n[h]=true;a[a.length]=h;f.push(e[h]);var o=t[Math.floor(h*4/i)];l=h*4&s;if(i<4+l)throw new Error("FAT boundary crossed: "+h+" 4 "+i);if(!e[o])break;h=__readInt32LE(e[o],l)}return{nodes:a,data:__toBuffer([f])}}function u(e,r,t,i){var n=e.length,a=[];var f=[],s=[],h=[];var l=i-1,o=0,u=0,c=0,_=0;for(o=0;o=n)c-=n;if(f[c])continue;h=[];for(u=c;u>=0;){f[u]=true;s[s.length]=u;h.push(e[u]);var d=t[Math.floor(u*4/i)];_=u*4&l;if(i<4+_)throw new Error("FAT boundary crossed: "+u+" 4 "+i);if(!e[d])break;u=__readInt32LE(e[d],_)}a[c]={nodes:s,data:__toBuffer([h])}}return a}function c(e,r,t,i,n,a,f){var s=0,h=i.length?2:0;var l=r[e].data;var u=0,c=0,d;for(;u0&&s!==E)r[s].name="!StreamData"}else if(w.size>=4096){w.storage="fat";if(r[w.start]===undefined)r[w.start]=o(t,w.start,r.fat_addrs,r.ssz);r[w.start].name=w.name;w.content=r[w.start].data.slice(0,w.size);prep_blob(w.content,0)}else{w.storage="minifat";if(s!==E&&w.start!==E&&r[s]){w.content=r[s].data.slice(w.start*x,w.start*x+w.size);prep_blob(w.content,0)}}a[d]=w;f.push(w)}}function _(e,r){return new Date((__readUInt32LE(e,r+4)/1e7*Math.pow(2,32)+__readUInt32LE(e,r)/1e7-11644473600)*1e3)}var d;function v(e,r){if(d==null)d=require("fs");return n(d.readFileSync(e),r)}function w(e,r){switch(r&&r.type||"base64"){case"file":return v(e,r);case"base64":return n(s2a(Base64.decode(e)),r);case"binary":return n(s2a(e),r);}return n(e,r)}function p(e,r){var t=r||{},i=t.root||"Root Entry";if(!e.FullPaths)e.FullPaths=[];if(!e.FileIndex)e.FileIndex=[];if(e.FullPaths.length!==e.FileIndex.length)throw new Error("inconsistent CFB structure");if(e.FullPaths.length===0){e.FullPaths[0]=i+"/";e.FileIndex[0]={name:i,type:5}}if(t.CLSID)e.FileIndex[0].clsid=t.CLSID;F(e)}function F(e){var r="Sh33tJ5";if(CFB.find(e,"/"+r))return;var t=new_buf(4);t[0]=55;t[1]=t[3]=50;t[2]=54;e.FileIndex.push({name:r,type:2,content:t,size:4,L:69,R:69,C:69});e.FullPaths.push(e.FullPaths[0]+r);I(e)}function I(e,n){p(e);var a=false,f=false;for(var s=e.FullPaths.length-1;s>=0;--s){var h=e.FileIndex[s];switch(h.type){case 0:if(f)a=true;else{e.FileIndex.pop();e.FullPaths.pop()}break;case 1:;case 2:;case 5:f=true;if(isNaN(h.R*h.L*h.C))a=true;if(h.R>-1&&h.L>-1&&h.R==h.L)a=true;break;default:a=true;break;}}if(!a&&!n)return;var l=new Date,o=0;var u=[];for(s=0;s1?1:-1;_.size=0;_.type=5}else if(d.slice(-1)=="/"){for(o=s+1;o=u.length?-1:o;for(o=s+1;o=u.length?-1:o;_.type=1}else{if(t(e.FullPaths[s+1]||"")==t(d))_.R=s+1;_.type=2}}}function g(e,r){I(e);var t=function(e){var r=0,t=0;for(var i=0;i>6;else t+=a+511>>9}var f=e.FullPaths.length+3>>2;var s=r+7>>3;var h=r+127>>7;var l=s+t+f+h;var o=l+127>>7;var u=o<=109?0:Math.ceil((o-109)/127);while(l+o+u+127>>7>o)u=++o<=109?0:Math.ceil((o-109)/127);var c=[1,u,o,h,f,t,r,0];e.FileIndex[0].size=r<<6;c[7]=(e.FileIndex[0].start=c[0]+c[1]+c[2]+c[3]+c[4]+c[5])+(c[6]+7>>3);return c}(e);var i=new_buf(t[7]<<9);var n=0,a=0;{for(n=0;n<8;++n)i.write_shift(1,y[n]);for(n=0;n<8;++n)i.write_shift(2,0);i.write_shift(2,62);i.write_shift(2,3);i.write_shift(2,65534);i.write_shift(2,9);i.write_shift(2,6);for(n=0;n<3;++n)i.write_shift(2,0);i.write_shift(4,0);i.write_shift(4,t[2]);i.write_shift(4,t[0]+t[1]+t[2]+t[3]-1);i.write_shift(4,0);i.write_shift(4,1<<12);i.write_shift(4,t[3]?t[0]+t[1]+t[2]-1:E);i.write_shift(4,t[3]);i.write_shift(-4,t[1]?t[0]-1:E);i.write_shift(4,t[1]);for(n=0;n<109;++n)i.write_shift(-4,n>9)}f(t[6]+7>>3);while(i.l&511)i.write_shift(-4,A.ENDOFCHAIN);a=n=0;for(s=0;s=4096)continue;l.start=a;f(h+63>>6)}while(i.l&511)i.write_shift(-4,A.ENDOFCHAIN);for(n=0;n=4096){i.l=l.start+1<<9;for(s=0;s0&&l.size<4096){for(s=0;s>2;n=r.charCodeAt(o++);s=(i&3)<<4|n>>4;a=r.charCodeAt(o++);h=(n&15)<<2|a>>6;l=a&63;if(isNaN(n)){h=l=64}else if(isNaN(a)){l=64}t+=e.charAt(f)+e.charAt(s)+e.charAt(h)+e.charAt(l)}return t},decode:function r(t){var i="";var n,a,f;var s,h,l,o;t=t.replace(/[^\w\+\/\=]/g,"");for(var c=0;c>4;i+=String.fromCharCode(n);l=e.indexOf(t.charAt(c++));a=(h&15)<<4|l>>2;if(l!==64){i+=String.fromCharCode(a)}o=e.indexOf(t.charAt(c++));f=(l&3)<<6|o;if(o!==64){i+=String.fromCharCode(f)}}return i}}}();var has_buf=typeof Buffer!=="undefined"&&typeof process!=="undefined"&&typeof process.versions!=="undefined"&&process.versions.node;function new_raw_buf(e){return new(has_buf?Buffer:Array)(e)}var s2a=function r(e){if(has_buf)return new Buffer(e,"binary");return e.split("").map(function(e){return e.charCodeAt(0)&255})};var chr0=/\u0000/g,chr1=/[\u0001-\u0006]/;var __toBuffer=function(e){var r=[];for(var t=0;t0&&Buffer.isBuffer(e[0][0])?Buffer.concat(e[0]):___toBuffer(e)};s2a=function(e){return new Buffer(e,"binary")};bconcat=function(e){return Buffer.isBuffer(e[0])?Buffer.concat(e):__bconcat(e)}}var __readUInt8=function(e,r){return e[r]};var __readUInt16LE=function(e,r){return e[r+1]*(1<<8)+e[r]};var __readInt16LE=function(e,r){var t=e[r+1]*(1<<8)+e[r];return t<32768?t:(65535-t+1)*-1};var __readUInt32LE=function(e,r){return e[r+3]*(1<<24)+(e[r+2]<<16)+(e[r+1]<<8)+e[r]};var __readInt32LE=function(e,r){return(e[r+3]<<24)+(e[r+2]<<16)+(e[r+1]<<8)+e[r]};function ReadShift(e,r){var t,i,n=0;switch(e){case 1:t=__readUInt8(this,this.l);break;case 2:t=(r!=="i"?__readUInt16LE:__readInt16LE)(this,this.l);break;case 4:t=__readInt32LE(this,this.l);break;case 16:n=2;i=__hexlify(this,this.l,e);}this.l+=e;if(n===0)return t;return i}var __writeUInt32LE=function(e,r,t){e[t]=r&255;e[t+1]=r>>>8&255;e[t+2]=r>>>16&255;e[t+3]=r>>>24&255};var __writeInt32LE=function(e,r,t){e[t]=r&255;e[t+1]=r>>8&255;e[t+2]=r>>16&255;e[t+3]=r>>24&255};function WriteShift(e,r,t){var i=0,n=0;switch(t){case"hex":for(;n>8}while(this.l>>=8;this[this.l+1]=r&255;break;case 4:i=4;__writeUInt32LE(this,r,this.l);break;case-4:i=4;__writeInt32LE(this,r,this.l);break;}this.l+=i;return this}function CheckField(e,r){var t=__hexlify(this,this.l,e.length>>1);if(t!==e)throw new Error(r+"Expected "+e+" saw "+t);this.l+=e.length>>1}function prep_blob(e,r){e.l=r;e.read_shift=ReadShift;e.chk=CheckField;e.write_shift=WriteShift}function new_buf(e){var r=new_raw_buf(e);prep_blob(r,0);return r}var CFB=function t(){var e={};e.version="0.13.1";function r(e,r){var t=e.split("/"),i=r.split("/");for(var n=0,a=0,f=Math.min(t.length,i.length);n0&&d!==E)y[d].name="!MiniFAT";y[w[0]].name="!FAT";y.fat_addrs=w;y.ssz=i;var S={},A=[],m=[],B=[],k={};u(_,y,C,A,n,S,m);h(m,k,B,A);A.shift();var L={FileIndex:m,FullPaths:B,FullPathDir:k};if(r&&r.raw)L.raw={header:g,sectors:C};return L}function a(e){e.chk(C,"Header Signature: ");e.chk(S,"CLSID: ");var r=e.read_shift(2,"u");return[e.read_shift(2,"u"),r]}function f(e,r){var t=9;e.l+=2;switch(t=e.read_shift(2)){case 9:if(r!=3)throw new Error("Sector Shift: Expected 9 saw "+t);break;case 12:if(r!=4)throw new Error("Sector Shift: Expected 12 saw "+t);break;default:throw new Error("Sector Shift: Expected 9 or 12 saw "+t);}e.chk("0600","Mini Sector Shift: ");e.chk("000000000000","Reserved: ")}function s(e,r){var t=Math.ceil(e.length/r)-1;var i=[];for(var n=1;n>>2)-1;if(!f)return;for(var h=0;h=0;){n[h]=true;a[a.length]=h;f.push(e[h]);var o=t[Math.floor(h*4/i)];l=h*4&s;if(i<4+l)throw new Error("FAT boundary crossed: "+h+" 4 "+i);if(!e[o])break;h=__readInt32LE(e[o],l)}return{nodes:a,data:__toBuffer([f])}}function c(e,r,t,i){var n=e.length,a=[];var f=[],s=[],h=[];var l=i-1,o=0,c=0,u=0,_=0;for(o=0;o=n)u-=n;if(f[u])continue;h=[];for(c=u;c>=0;){f[c]=true;s[s.length]=c;h.push(e[c]);var d=t[Math.floor(c*4/i)];_=c*4&l;if(i<4+_)throw new Error("FAT boundary crossed: "+c+" 4 "+i);if(!e[d])break;c=__readInt32LE(e[d],_)}a[u]={nodes:s,data:__toBuffer([h])}}return a}function u(e,r,t,i,n,a,f){var s=0,h=i.length?2:0;var l=r[e].data;var c=0,u=0,d;for(;c0&&s!==E)r[s].name="!StreamData"}else if(w.size>=4096){w.storage="fat";if(r[w.start]===undefined)r[w.start]=o(t,w.start,r.fat_addrs,r.ssz);r[w.start].name=w.name;w.content=r[w.start].data.slice(0,w.size);prep_blob(w.content,0)}else{w.storage="minifat";if(s!==E&&w.start!==E&&r[s]){w.content=r[s].data.slice(w.start*x,w.start*x+w.size);prep_blob(w.content,0)}}a[d]=w;f.push(w)}}function _(e,r){return new Date((__readUInt32LE(e,r+4)/1e7*Math.pow(2,32)+__readUInt32LE(e,r)/1e7-11644473600)*1e3)}var d;function v(e,r){if(d==null)d=require("fs");return n(d.readFileSync(e),r)}function w(e,r){switch(r&&r.type||"base64"){case"file":return v(e,r);case"base64":return n(s2a(Base64.decode(e)),r);case"binary":return n(s2a(e),r);}return n(e,r)}function p(e,r){var t=r||{},i=t.root||"Root Entry";if(!e.FullPaths)e.FullPaths=[];if(!e.FileIndex)e.FileIndex=[];if(e.FullPaths.length!==e.FileIndex.length)throw new Error("inconsistent CFB structure");if(e.FullPaths.length===0){e.FullPaths[0]=i+"/";e.FileIndex[0]={name:i,type:5}}if(t.CLSID)e.FileIndex[0].clsid=t.CLSID;F(e)}function F(e){var r="Sh33tJ5";if(CFB.find(e,"/"+r))return;var t=new_buf(4);t[0]=55;t[1]=t[3]=50;t[2]=54;e.FileIndex.push({name:r,type:2,content:t,size:4,L:69,R:69,C:69});e.FullPaths.push(e.FullPaths[0]+r);g(e)}function g(e,n){p(e);var a=false,f=false;for(var s=e.FullPaths.length-1;s>=0;--s){var h=e.FileIndex[s];switch(h.type){case 0:if(f)a=true;else{e.FileIndex.pop();e.FullPaths.pop()}break;case 1:;case 2:;case 5:f=true;if(isNaN(h.R*h.L*h.C))a=true;if(h.R>-1&&h.L>-1&&h.R==h.L)a=true;break;default:a=true;break;}}if(!a&&!n)return;var l=new Date(1987,1,19),o=0;var c=[];for(s=0;s1?1:-1;_.size=0;_.type=5}else if(d.slice(-1)=="/"){for(o=s+1;o=c.length?-1:o;for(o=s+1;o=c.length?-1:o;_.type=1}else{if(t(e.FullPaths[s+1]||"")==t(d))_.R=s+1;_.type=2}}}function I(e,r){g(e);var t=function(e){var r=0,t=0;for(var i=0;i>6;else t+=a+511>>9}var f=e.FullPaths.length+3>>2;var s=r+7>>3;var h=r+127>>7;var l=s+t+f+h;var o=l+127>>7;var c=o<=109?0:Math.ceil((o-109)/127);while(l+o+c+127>>7>o)c=++o<=109?0:Math.ceil((o-109)/127);var u=[1,c,o,h,f,t,r,0];e.FileIndex[0].size=r<<6;u[7]=(e.FileIndex[0].start=u[0]+u[1]+u[2]+u[3]+u[4]+u[5])+(u[6]+7>>3);return u}(e);var i=new_buf(t[7]<<9);var n=0,a=0;{for(n=0;n<8;++n)i.write_shift(1,y[n]);for(n=0;n<8;++n)i.write_shift(2,0);i.write_shift(2,62);i.write_shift(2,3);i.write_shift(2,65534);i.write_shift(2,9);i.write_shift(2,6);for(n=0;n<3;++n)i.write_shift(2,0);i.write_shift(4,0);i.write_shift(4,t[2]);i.write_shift(4,t[0]+t[1]+t[2]+t[3]-1);i.write_shift(4,0);i.write_shift(4,1<<12);i.write_shift(4,t[3]?t[0]+t[1]+t[2]-1:E);i.write_shift(4,t[3]);i.write_shift(-4,t[1]?t[0]-1:E);i.write_shift(4,t[1]);for(n=0;n<109;++n)i.write_shift(-4,n>9)}f(t[6]+7>>3);while(i.l&511)i.write_shift(-4,A.ENDOFCHAIN);a=n=0;for(s=0;s=4096)continue;l.start=a;f(h+63>>6)}while(i.l&511)i.write_shift(-4,A.ENDOFCHAIN);for(n=0;n=4096){i.l=l.start+1<<9;for(s=0;s0&&l.size<4096){for(s=0;s> 2); - - c2 = input.charCodeAt(i++); - e2 = ((c1 & 3) << 4) | (c2 >> 4); - - c3 = input.charCodeAt(i++); - e3 = ((c2 & 15) << 2) | (c3 >> 6); - e4 = (c3 & 63); - if (isNaN(c2)) { e3 = e4 = 64; } - else if (isNaN(c3)) { e4 = 64; } - o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4); - } - return o; - }, - decode: function b64_decode(input) { - var o = ""; - var c1, c2, c3; - var e1, e2, e3, e4; - input = input.replace(/[^\w\+\/\=]/g, ""); - for(var i = 0; i < input.length;) { - e1 = map.indexOf(input.charAt(i++)); - e2 = map.indexOf(input.charAt(i++)); - c1 = (e1 << 2) | (e2 >> 4); - o += String.fromCharCode(c1); - - e3 = map.indexOf(input.charAt(i++)); - c2 = ((e2 & 15) << 4) | (e3 >> 2); - if (e3 !== 64) { o += String.fromCharCode(c2); } - - e4 = map.indexOf(input.charAt(i++)); - c3 = ((e3 & 3) << 6) | e4; - if (e4 !== 64) { o += String.fromCharCode(c3); } - } - return o; - } - }; -})(); -var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && process.versions.node); - -function new_raw_buf(len) { - /* jshint -W056 */ - // $FlowIgnore - return new (has_buf ? Buffer : Array)(len); - /* jshint +W056 */ -} - -var s2a = function s2a(s) { - if(has_buf) return new Buffer(s, "binary"); - return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); +/*:: +declare var DO_NOT_EXPORT_CFB:?boolean; +type SectorEntry = { + name?:string; + nodes?:Array; + data:RawBytes; }; - -var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/; +type SectorList = { + [k:string|number]:SectorEntry; + name:?string; + fat_addrs:Array; + ssz:number; +} +type CFBFiles = {[n:string]:CFBEntry}; +*/ /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ -var exports = {}; -exports.version = '0.13.0'; +var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; +exports.version = '0.13.1'; /* [MS-CFB] 2.6.4 */ -function namecmp(l, r) { +function namecmp(l/*:string*/, r/*:string*/)/*:number*/ { var L = l.split("/"), R = r.split("/"); for(var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) { if((c = L[i].length - R[i].length)) return c; @@ -79,18 +48,18 @@ function namecmp(l, r) { } return L.length - R.length; } -function dirname(p) { +function dirname(p/*:string*/)/*:string*/ { if(p.charAt(p.length - 1) == "/") return (p.slice(0,-1).indexOf("/") === -1) ? p : dirname(p.slice(0, -1)); var c = p.lastIndexOf("/"); return (c === -1) ? p : p.slice(0, c+1); } -function filename(p) { +function filename(p/*:string*/)/*:string*/ { if(p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1)); var c = p.lastIndexOf("/"); return (c === -1) ? p : p.slice(c+1); } -function parse(file, options) { +function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ { var mver = 3; var ssz = 512; var nmfs = 0; // number of mini FAT sectors @@ -99,10 +68,10 @@ var dir_start = 0; var minifat_start = 0; var difat_start = 0; -var fat_addrs = []; // locations of FAT sectors +var fat_addrs/*:Array*/ = []; // locations of FAT sectors /* [MS-CFB] 2.2 Compound File Header */ -var blob = file.slice(0,512); +var blob/*:CFBlob*/ = /*::(*/file.slice(0,512)/*:: :any)*/; prep_blob(blob, 0); /* major version */ @@ -114,14 +83,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 dir_cnt = blob.read_shift(4, 'i'); +var dir_cnt/*:number*/ = blob.read_shift(4, 'i'); if(mver === 3 && dir_cnt !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + dir_cnt); // Number of FAT Sectors @@ -156,12 +125,12 @@ for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ } /** Break the file up into sectors */ -var sectors = sectorify(file, ssz); +var sectors/*:Array*/ = sectorify(file, ssz); sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs); /** Chains */ -var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz); +var sector_list/*:SectorList*/ = 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"; @@ -170,7 +139,7 @@ sector_list.fat_addrs = fat_addrs; sector_list.ssz = ssz; /* [MS-CFB] 2.6.1 Compound File Directory Entry */ -var files = {}, Paths = [], 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); @@ -188,7 +157,7 @@ return o; } // 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: '); @@ -196,11 +165,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 @@ -222,18 +191,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 = []; + 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 = [], q = []; + var dad/*:Array*/ = [], q/*:Array*/ = []; for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } @@ -273,8 +242,8 @@ function build_full_paths(FI, FPD, FP, Paths) { /** 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 bits */ -function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { - var q = ENDOFCHAIN; +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*/) { @@ -289,8 +258,8 @@ 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 buf = [], buf_chain = []; +function get_sector_list(sectors/*:Array*/, start/*:number*/, fat_addrs/*:Array*/, ssz/*:number*/, chkd/*:?Array*/)/*:SectorEntry*/ { + var buf/*:Array*/ = [], buf_chain/*:Array*/ = []; if(!chkd) chkd = []; var modulus = ssz - 1, j = 0, jj = 0; for(j=start; j>=0;) { @@ -307,12 +276,12 @@ 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 = ([]); - var chkd = [], buf = [], buf_chain = []; +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]) continue; buf_chain = []; @@ -320,29 +289,29 @@ function make_sector_list(sectors, dir_start, fat_addrs, ssz) { 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) { +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; for(; i < sector.length; i+= 128) { - var blob = sector.slice(i, i+128); + var blob/*:CFBlob*/ = /*::(*/sector.slice(i, i+128)/*:: :any)*/; prep_blob(blob, 64); namelen = blob.read_shift(2); name = __utf16le(blob,0,namelen-pl); Paths.push(name); - var o = ({ + var o/*:CFBEntry*/ = ({ name: name, type: blob.read_shift(1), color: blob.read_shift(1), @@ -354,9 +323,9 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil start: 0, size: 0 }); - var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + 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 = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + 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'); @@ -369,12 +338,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 && sector_list[minifat_store]) { - 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); } } @@ -383,46 +352,46 @@ 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 read_file(filename, options) { +var fs/*:: = require('fs'); */; +function read_file(filename/*:string*/, options/*:CFBReadOpts*/) { if(fs == null) fs = require('fs'); return parse(fs.readFileSync(filename), options); } -function read(blob, options) { +function read(blob/*:RawBytes|string*/, options/*:CFBReadOpts*/) { switch(options && options.type || "base64") { - case "file": return read_file(blob, options); - case "base64": return parse(s2a(Base64.decode(blob)), options); - case "binary": return parse(s2a(blob), options); + case "file": /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */return read_file(blob, options); + case "base64": /*:: if(typeof blob !== 'string') throw "Must pass a base64-encoded binary string when type='file'"; */return parse(s2a(Base64.decode(blob)), options); + case "binary": /*:: if(typeof blob !== 'string') throw "Must pass a binary string when type='file'"; */return parse(s2a(blob), options); } - return parse(blob, options); + return parse(/*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */blob, options); } -function init_cfb(cfb, opts) { +function init_cfb(cfb/*:CFBContainer*/, opts/*:?any*/)/*:void*/ { var o = opts || {}, root = o.root || "Root Entry"; if(!cfb.FullPaths) cfb.FullPaths = []; if(!cfb.FileIndex) cfb.FileIndex = []; if(cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure"); if(cfb.FullPaths.length === 0) { cfb.FullPaths[0] = root + "/"; - cfb.FileIndex[0] = ({ name: root, type: 5 }); + cfb.FileIndex[0] = ({ name: root, type: 5 }/*:any*/); } if(o.CLSID) cfb.FileIndex[0].clsid = o.CLSID; seed_cfb(cfb); } -function seed_cfb(cfb) { +function seed_cfb(cfb/*:CFBContainer*/)/*:void*/ { var nm = "\u0001Sh33tJ5"; if(CFB.find(cfb, "/" + nm)) return; var p = new_buf(4); p[0] = 55; p[1] = p[3] = 50; p[2] = 54; - cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 })); + cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 }/*:any*/)); cfb.FullPaths.push(cfb.FullPaths[0] + nm); rebuild_cfb(cfb); } -function rebuild_cfb(cfb, f) { +function rebuild_cfb(cfb/*:CFBContainer*/, f/*:?boolean*/)/*:void*/ { init_cfb(cfb); var gc = false, s = false; for(var i = cfb.FullPaths.length - 1; i >= 0; --i) { @@ -442,8 +411,8 @@ function rebuild_cfb(cfb, f) { } if(!gc && !f) return; - var now = new Date(), j = 0; - var data = []; + var now = new Date(1987, 1, 19), j = 0; + var data/*:Array<[string, CFBEntry]>*/ = []; for(i = 0; i < cfb.FullPaths.length; ++i) { if(cfb.FileIndex[i].type === 0) continue; data.push([cfb.FullPaths[i], cfb.FileIndex[i]]); @@ -458,7 +427,7 @@ function rebuild_cfb(cfb, f) { clsid: HEADER_CLSID, ct: now, mt: now, content: null - })]); + }/*:any*/)]); } data.sort(function(x,y) { return namecmp(x[0], y[0]); }); @@ -491,14 +460,15 @@ function rebuild_cfb(cfb, f) { } -function _write(cfb, options) { +function _write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes*/ { rebuild_cfb(cfb); - var L = (function(cfb){ + var L = (function(cfb/*:CFBContainer*/)/*:Array*/{ var mini_size = 0, fat_size = 0; for(var i = 0; i < cfb.FileIndex.length; ++i) { var file = cfb.FileIndex[i]; if(!file.content) continue; -var flen = file.content.length; + /*:: if(file.content == null) throw new Error("unreachable"); */ + var flen = file.content.length; if(flen === 0){} else if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6; else fat_size += (flen + 0x01FF) >> 9; @@ -543,7 +513,7 @@ var flen = file.content.length; o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1); } } - var chainit = function(w) { + var chainit = function(w/*:number*/)/*:void*/ { for(T += w; i> 9); @@ -568,7 +539,8 @@ flen = file.content.length; for(j = 0; j < cfb.FileIndex.length; ++j) { file = cfb.FileIndex[j]; if(!file.content) continue; -flen = file.content.length; + /*:: if(file.content == null) throw new Error("unreachable"); */ + flen = file.content.length; if(!flen || flen >= 0x1000) continue; file.start = T; chainit((flen + 0x3F) >> 6); @@ -602,7 +574,8 @@ flen = file.content.length; } for(i = 1; i < cfb.FileIndex.length; ++i) { file = cfb.FileIndex[i]; -if(file.size >= 0x1000) { + /*:: if(!file.content) throw new Error("unreachable"); */ + if(file.size >= 0x1000) { o.l = (file.start+1) << 9; for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]); for(; j & 0x1FF; ++j) o.write_shift(1, 0); @@ -610,24 +583,25 @@ if(file.size >= 0x1000) { } for(i = 1; i < cfb.FileIndex.length; ++i) { file = cfb.FileIndex[i]; -if(file.size > 0 && file.size < 0x1000) { + /*:: if(!file.content) throw new Error("unreachable"); */ + if(file.size > 0 && file.size < 0x1000) { for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]); for(; j & 0x3F; ++j) o.write_shift(1, 0); } } - + while(o.l < o.length) o.write_shift(1, 0); return o; } /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ -function find(cfb, path) { +function find(cfb/*:CFBContainer*/, path/*:string*/)/*:?CFBEntry*/ { //return cfb.find(path); - var UCFullPaths = cfb.FullPaths.map(function(x) { return x.toUpperCase(); }); - var UCPaths = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; }); - var k = false; + var UCFullPaths/*:Array*/ = cfb.FullPaths.map(function(x) { return x.toUpperCase(); }); + var UCPaths/*:Array*/ = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; }); + var k/*:boolean*/ = false; if(path.charCodeAt(0) === 47 /* "/" */) { k = true; path = UCFullPaths[0].slice(0, -1) + path; } else k = path.indexOf("/") !== -1; - var UCPath = path.toUpperCase(); - var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); + var UCPath/*:string*/ = path.toUpperCase(); + var w/*:number*/ = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); if(w !== -1) return cfb.FileIndex[w]; UCPath = UCPath.replace(chr0,'').replace(chr1,'!'); @@ -663,42 +637,50 @@ var consts = { EntryTypes: ['unknown','storage','stream','lockbytes','property','root'] }; -function write_file(cfb, filename, options) { +function write_file(cfb/*:CFBContainer*/, filename/*:string*/, options/*:CFBWriteOpts*/)/*:void*/ { var o = _write(cfb, options); -fs.writeFileSync(filename, o); + /*:: if(typeof Buffer == 'undefined' || !Buffer.isBuffer(o) || !(o instanceof Buffer)) throw new Error("unreachable"); */ + fs.writeFileSync(filename, o); } -function a2s(o) { +function a2s(o/*:RawBytes*/)/*:string*/ { var out = new Array(o.length); for(var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]); return out.join(""); } -function write(cfb, options) { +function write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string*/ { var o = _write(cfb, options); switch(options && options.type) { - case "file": fs.writeFileSync(options.filename, (o)); return o; + case "file": fs.writeFileSync(options.filename, (o/*:any*/)); return o; case "binary": return a2s(o); case "base64": return Base64.encode(a2s(o)); } return o; } -function cfb_new(opts) { - var o = ({}); +function cfb_new(opts/*:?any*/)/*:CFBContainer*/ { + var o/*:CFBContainer*/ = ({}/*:any*/); init_cfb(o, opts); return o; } -function cfb_add(cfb, name, content, opts) { +function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, opts/*:?any*/)/*:CFBEntry*/ { init_cfb(cfb); var file = CFB.find(cfb, name); if(!file) { - file = ({name: filename(name)}); + var fpath = cfb.FullPaths[0]; + if(name.slice(0, fpath.length) == fpath) fpath = name; + else { + if(fpath.slice(-1) != "/") fpath += "/"; + fpath = (fpath + name).replace("//","/"); + } + file = ({name: filename(name)}/*:any*/); cfb.FileIndex.push(file); - cfb.FullPaths.push(name); + cfb.FullPaths.push(fpath); CFB.utils.cfb_gc(cfb); } -file.content = (content); + /*:: if(!file) throw new Error("unreachable"); */ + file.content = (content/*:any*/); file.size = content ? content.length : 0; if(opts) { if(opts.CLSID) file.clsid = opts.CLSID; @@ -706,7 +688,7 @@ file.content = (content); return file; } -function cfb_del(cfb, name) { +function cfb_del(cfb/*:CFBContainer*/, name/*:string*/)/*:boolean*/ { init_cfb(cfb); var file = CFB.find(cfb, name); if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) { @@ -717,7 +699,7 @@ function cfb_del(cfb, name) { return false; } -function cfb_mov(cfb, old_name, new_name) { +function cfb_mov(cfb/*:CFBContainer*/, old_name/*:string*/, new_name/*:string*/)/*:boolean*/ { init_cfb(cfb); var file = CFB.find(cfb, old_name); if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) { @@ -728,7 +710,7 @@ function cfb_mov(cfb, old_name, new_name) { return false; } -function cfb_gc(cfb) { rebuild_cfb(cfb, true); } +function cfb_gc(cfb/*:CFBContainer*/)/*:void*/ { rebuild_cfb(cfb, true); } exports.find = find; exports.read = read; diff --git a/index.html b/index.html index b314bfe..26dfea2 100644 --- a/index.html +++ b/index.html @@ -31,73 +31,75 @@ a { text-decoration: none } Advanced Demo Options: Use readAsBinaryString: (when available) + +Export loaded data

 
+ +