diff --git a/.flowconfig b/.flowconfig index 0e7334d..ffd95f2 100644 --- a/.flowconfig +++ b/.flowconfig @@ -34,3 +34,6 @@ module.file_ext=.js module.file_ext=.njs module.ignore_non_literal_requires=true suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore + +[lints] +deprecated-declare-exports=off diff --git a/bits/31_version.js b/bits/31_version.js index 80083e4..cf1bf4a 100644 --- a/bits/31_version.js +++ b/bits/31_version.js @@ -1 +1 @@ -exports.version = '1.0.2'; +exports.version = '1.0.3'; diff --git a/bits/46_readdir.js b/bits/46_readdir.js index f01cede..2069373 100644 --- a/bits/46_readdir.js +++ b/bits/46_readdir.js @@ -37,14 +37,14 @@ function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sector 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)/*:any*/); - prep_blob(o.content, 0); } else { o.storage = 'minifat'; - if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); - prep_blob(o.content, 0); } } + if(o.content) prep_blob(o.content, 0); files[name] = o; FileIndex.push(o); } diff --git a/cfb.flow.js b/cfb.flow.js index c9e3dc7..6bf3436 100644 --- a/cfb.flow.js +++ b/cfb.flow.js @@ -180,7 +180,7 @@ type CFBFiles = {[n:string]:CFBEntry}; /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; -exports.version = '1.0.2'; +exports.version = '1.0.3'; /* [MS-CFB] 2.6.4 */ function namecmp(l/*:string*/, r/*:string*/)/*:number*/ { var L = l.split("/"), R = r.split("/"); @@ -495,14 +495,14 @@ function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sector 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)/*:any*/); - prep_blob(o.content, 0); } else { o.storage = 'minifat'; - if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); - prep_blob(o.content, 0); } } + if(o.content) prep_blob(o.content, 0); files[name] = o; FileIndex.push(o); } diff --git a/cfb.js b/cfb.js index e924d2a..3078b62 100644 --- a/cfb.js +++ b/cfb.js @@ -162,7 +162,7 @@ function new_buf(sz) { /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '1.0.2'; +exports.version = '1.0.3'; /* [MS-CFB] 2.6.4 */ function namecmp(l, r) { var L = l.split("/"), R = r.split("/"); @@ -477,14 +477,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil 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 && sector_list[minifat_store]) { + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); - prep_blob(o.content, 0); } } + if(o.content) prep_blob(o.content, 0); files[name] = o; FileIndex.push(o); } diff --git a/dist/cfb.js b/dist/cfb.js index e924d2a..3078b62 100644 --- a/dist/cfb.js +++ b/dist/cfb.js @@ -162,7 +162,7 @@ function new_buf(sz) { /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '1.0.2'; +exports.version = '1.0.3'; /* [MS-CFB] 2.6.4 */ function namecmp(l, r) { var L = l.split("/"), R = r.split("/"); @@ -477,14 +477,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil 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 && sector_list[minifat_store]) { + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); - prep_blob(o.content, 0); } } + if(o.content) prep_blob(o.content, 0); files[name] = o; FileIndex.push(o); } diff --git a/dist/cfb.min.js b/dist/cfb.min.js index a856dd2..f2304a6 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 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]/g;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="1.0.2";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&&c!==y)C[c].name="!MiniFAT";C[w[0]].name="!FAT";C.fat_addrs=w;C.ssz=i;var S={},A=[],m=[],B=[];v(f,C,E,A,n,S,m,c);o(m,B,A);A.shift();var L={FileIndex:m,FullPaths:B};if(r&&r.raw)L.raw={header:g,sectors:E};return L}function s(e){e.chk(S,"Header Signature: ");e.chk(m,"CLSID: ");var r=e.read_shift(2,"u");return[e.read_shift(2,"u"),r]}function h(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 l(e,r){var t=Math.ceil(e.length/r)-1;var i=[];for(var n=1;n0&&f>=0){a.push(r.slice(f*C,f*C+C));n-=C;f=__readInt32LE(t,f*4)}if(a.length===0)return new_buf(0);return bconcat(a).slice(0,e.size)}function u(e,r,t,i,n){var a=y;if(e===y){if(r!==0)throw new Error("DIFAT chain shorter than expected")}else if(e!==-1){var f=t[e],s=(i>>>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 d(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 v(e,r,t,i,n,a,f,s){var h=0,l=i.length?2:0;var o=r[e].data;var u=0,d=0,v;for(;u0&&h!==y)r[h].name="!StreamData"}else if(F.size>=4096){F.storage="fat";if(r[F.start]===undefined)r[F.start]=_(t,F.start,r.fat_addrs,r.ssz);r[F.start].name=F.name;F.content=r[F.start].data.slice(0,F.size);prep_blob(F.content,0)}else{F.storage="minifat";if(h!==y&&F.start!==y&&r[h]){F.content=c(F,r[h].data,(r[s]||{}).data);prep_blob(F.content,0)}}a[v]=F;f.push(F)}}function w(e,r){return new Date((__readUInt32LE(e,r+4)/1e7*Math.pow(2,32)+__readUInt32LE(e,r)/1e7-11644473600)*1e3)}function p(e,r){a();return f(n.readFileSync(e),r)}function F(e,r){switch(r&&r.type||"base64"){case"file":return p(e,r);case"base64":return f(s2a(Base64.decode(e)),r);case"binary":return f(s2a(e),r);}return f(e,r)}function g(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;I(e)}function I(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);b(e)}function b(e,n){g(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 x(e,r){var t=r||{};b(e);var i=function(e){var r=0,t=0;for(var i=0;i0){if(a<4096)r+=a+63>>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 n=new_buf(i[7]<<9);var a=0,f=0;{for(a=0;a<8;++a)n.write_shift(1,A[a]);for(a=0;a<8;++a)n.write_shift(2,0);n.write_shift(2,62);n.write_shift(2,3);n.write_shift(2,65534);n.write_shift(2,9);n.write_shift(2,6);for(a=0;a<3;++a)n.write_shift(2,0);n.write_shift(4,0);n.write_shift(4,i[2]);n.write_shift(4,i[0]+i[1]+i[2]+i[3]-1);n.write_shift(4,0);n.write_shift(4,1<<12);n.write_shift(4,i[3]?i[0]+i[1]+i[2]-1:y);n.write_shift(4,i[3]);n.write_shift(-4,i[1]?i[0]-1:y);n.write_shift(4,i[1]);for(a=0;a<109;++a)n.write_shift(-4,a>9)}s(i[6]+7>>3);while(n.l&511)n.write_shift(-4,B.ENDOFCHAIN);f=a=0;for(h=0;h=4096)continue;o.start=f;s(l+63>>6)}while(n.l&511)n.write_shift(-4,B.ENDOFCHAIN);for(a=0;a=4096){n.l=o.start+1<<9;for(h=0;h0&&o.size<4096){for(h=0;h>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]/g;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="1.0.3";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&&c!==y)C[c].name="!MiniFAT";C[w[0]].name="!FAT";C.fat_addrs=w;C.ssz=i;var S={},A=[],m=[],B=[];v(f,C,E,A,n,S,m,c);o(m,B,A);A.shift();var L={FileIndex:m,FullPaths:B};if(r&&r.raw)L.raw={header:g,sectors:E};return L}function s(e){e.chk(S,"Header Signature: ");e.chk(m,"CLSID: ");var r=e.read_shift(2,"u");return[e.read_shift(2,"u"),r]}function h(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 l(e,r){var t=Math.ceil(e.length/r)-1;var i=[];for(var n=1;n0&&f>=0){a.push(r.slice(f*C,f*C+C));n-=C;f=__readInt32LE(t,f*4)}if(a.length===0)return new_buf(0);return bconcat(a).slice(0,e.size)}function u(e,r,t,i,n){var a=y;if(e===y){if(r!==0)throw new Error("DIFAT chain shorter than expected")}else if(e!==-1){var f=t[e],s=(i>>>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 d(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 v(e,r,t,i,n,a,f,s){var h=0,l=i.length?2:0;var o=r[e].data;var u=0,d=0,v;for(;u0&&h!==y)r[h].name="!StreamData"}else if(F.size>=4096){F.storage="fat";if(r[F.start]===undefined)r[F.start]=_(t,F.start,r.fat_addrs,r.ssz);r[F.start].name=F.name;F.content=r[F.start].data.slice(0,F.size)}else{F.storage="minifat";if(F.size<0)F.size=0;else if(h!==y&&F.start!==y&&r[h]){F.content=c(F,r[h].data,(r[s]||{}).data)}}if(F.content)prep_blob(F.content,0);a[v]=F;f.push(F)}}function w(e,r){return new Date((__readUInt32LE(e,r+4)/1e7*Math.pow(2,32)+__readUInt32LE(e,r)/1e7-11644473600)*1e3)}function p(e,r){a();return f(n.readFileSync(e),r)}function F(e,r){switch(r&&r.type||"base64"){case"file":return p(e,r);case"base64":return f(s2a(Base64.decode(e)),r);case"binary":return f(s2a(e),r);}return f(e,r)}function g(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;I(e)}function I(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);b(e)}function b(e,n){g(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 x(e,r){var t=r||{};b(e);var i=function(e){var r=0,t=0;for(var i=0;i0){if(a<4096)r+=a+63>>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 n=new_buf(i[7]<<9);var a=0,f=0;{for(a=0;a<8;++a)n.write_shift(1,A[a]);for(a=0;a<8;++a)n.write_shift(2,0);n.write_shift(2,62);n.write_shift(2,3);n.write_shift(2,65534);n.write_shift(2,9);n.write_shift(2,6);for(a=0;a<3;++a)n.write_shift(2,0);n.write_shift(4,0);n.write_shift(4,i[2]);n.write_shift(4,i[0]+i[1]+i[2]+i[3]-1);n.write_shift(4,0);n.write_shift(4,1<<12);n.write_shift(4,i[3]?i[0]+i[1]+i[2]-1:y);n.write_shift(4,i[3]);n.write_shift(-4,i[1]?i[0]-1:y);n.write_shift(4,i[1]);for(a=0;a<109;++a)n.write_shift(-4,a>9)}s(i[6]+7>>3);while(n.l&511)n.write_shift(-4,B.ENDOFCHAIN);f=a=0;for(h=0;h=4096)continue;o.start=f;s(l+63>>6)}while(n.l&511)n.write_shift(-4,B.ENDOFCHAIN);for(a=0;a=4096){n.l=o.start+1<<9;for(h=0;h0&&o.size<4096){for(h=0;h void) | null; @@ -58,6 +59,9 @@ function parsetest(x, cfb) { it('should handle "!" aliases', function() { names.forEach(function(n) { if(CFB.find(cfb,n[0]) != CFB.find(cfb,n[1])) throw new Error("Bad name: " + n.join(" != ")); }); }); + it('should handle size < 0', function() { + cfb.FileIndex.forEach(function(p, i) { if(p.size < 0) throw new Error(cfb.FullPaths[i] + " size=" + p.size); }); + }); }); describe(x + ' should roundtrip', function() { var data, newcfb; @@ -164,5 +168,8 @@ describe('api', function() { var file = CFB.find(cfb, '/dafuq'); if(!file || !file.content) throw new Error("Cannot find /dafuq"); if(file.content.length != 3) throw new Error("Bad content length " + file.content.length); + file = CFB.find(newcfb, '/dafuq'); + if(!file || !file.content) throw new Error("Cannot find /dafuq"); + if(file.content.length != 3) throw new Error("Bad content length " + file.content.length); }); }); diff --git a/types/bin_cfb.ts b/types/bin_cfb.ts index e49ba74..1d233e3 100755 --- a/types/bin_cfb.ts +++ b/types/bin_cfb.ts @@ -36,10 +36,10 @@ if(program.create) { if(!fs.existsSync(program.args[0])) die(1, "must specify a filename"); -const opts: X.CFBParsingOptions = {type:'file'}; +const opts: X.CFB$ParsingOptions = {type:'file'}; if(program.dev) opts.WTF = true; -const cfb: X.CFBContainer = X.read(program.args[0], opts); +const cfb: X.CFB$Container = X.read(program.args[0], opts); if(program.quiet) exit(0); if(program.dump) { @@ -61,7 +61,7 @@ if(program.listFiles) { let cnt = 0, rootsize = 0, filesize = 0; console.log(" Length Date Time Name"); console.log(" -------- ---- ---- ----"); - cfb.FileIndex.forEach((file: X.CFBEntry, i: number) => { + cfb.FileIndex.forEach((file: X.CFB$Entry, i: number) => { switch(file.type) { case 5: basetime = file.ct || file.mt || basetime; @@ -85,7 +85,7 @@ const mkdirp = (path: string) => { path.split("/").reduce((acc: string, p: strin return acc; }, ""); }; -const write = (path: string, data: X.CFBEntry) => { +const write = (path: string, data: X.CFB$Entry) => { logit("write", fix_string(path)); fs.writeFileSync(path, /*::new Buffer((*/data.content/*:: :any))*/); }; @@ -110,7 +110,7 @@ if(program.delete) { if(program.args.length > 1) { program.args.slice(1).forEach((x: string) => { - const data/*:?CFBEntry*/ = X.find(cfb, x); + const data: X.CFB$Entry = X.find(cfb, x); if(!data) { console.error(x + ": file not found"); return; } if(data.type !== 2) { console.error(x + ": not a file"); return; } const idx = cfb.FileIndex.indexOf(data), path = cfb.FullPaths[idx]; diff --git a/types/index.d.ts b/types/index.d.ts index cd5aef9..3d04fb0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -5,100 +5,102 @@ export const version: string; /** Parse a buffer or array */ -export function parse(f: CFB$Blob, options?: CFBParsingOptions): CFBContainer; +export function parse(f: CFB$Blob, options?: CFB$ParsingOptions): CFB$Container; /** Read a blob or file or binary string */ -export function read(f: CFB$Blob | string, options?: CFBParsingOptions): CFBContainer; +export function read(f: CFB$Blob | string, options?: CFB$ParsingOptions): CFB$Container; /** Find a file entry given a path or file name */ -export function find(cfb: CFBContainer, path: string): CFBEntry | null; +export function find(cfb: CFB$Container, path: string): CFB$Entry | null; /** Generate a container file */ -export function write(cfb: CFBContainer, options?: any): any; +export function write(cfb: CFB$Container, options?: any): any; /** Write a container file to the filesystem */ -export function writeFile(cfb: CFBContainer, filename: string, options?: any): any; +export function writeFile(cfb: CFB$Container, filename: string, options?: any): any; /** Utility functions */ export const utils: CFB$Utils; /** Options for read and readFile */ -export interface CFBParsingOptions { - /** Input data encoding */ - type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array'; - /** If true, throw errors when features are not understood */ - WTF?: boolean; - /** If true, include raw data in output */ - raw?: boolean; +export interface CFB$ParsingOptions { + /** Input data encoding */ + type?: 'base64' | 'binary' | 'buffer' | 'file' | 'array'; + + /** If true, throw errors when features are not understood */ + WTF?: boolean; + + /** If true, include raw data in output */ + raw?: boolean; } export type CFB$Blob = Buffer | number[] | Uint8Array; -export enum CFBEntryType { unknown, storage, stream, lockbytes, property, root } -export enum CFBStorageType { fat, minifat } +export enum CFB$EntryType { unknown, storage, stream, lockbytes, property, root } +export enum CFB$StorageType { fat, minifat } /** CFB File Entry Object */ -export interface CFBEntry { - /** Case-sensitive internal name */ - name: string; +export interface CFB$Entry { + /** Case-sensitive internal name */ + name: string; - /** CFB type (salient types: stream, storage) -- see CFBEntryType */ - type: number; + /** CFB type (salient types: stream, storage) -- see CFB$EntryType */ + type: number; - /** Raw Content (Buffer when available, Array of bytes otherwise) */ - content: CFB$Blob; + /** Raw Content (Buffer when available, Array of bytes otherwise) */ + content: CFB$Blob; - /** Creation Time */ - ct?: Date; + /** Creation Time */ + ct?: Date; - /** Modification Time */ - mt?: Date; + /** Modification Time */ + mt?: Date; - /** Red/Black Tree color: 0 = red, 1 = black */ - color: number; + /** Red/Black Tree color: 0 = red, 1 = black */ + color: number; - /** Class ID represented as hex string */ - clsid: string; + /** Class ID represented as hex string */ + clsid: string; - /** User-Defined State Bits */ - state: number; + /** User-Defined State Bits */ + state: number; - /** Starting Sector */ - start: number; + /** Starting Sector */ + start: number; - /** Data Size */ - size: number; + /** Data Size */ + size: number; - /** Storage location -- see CFBStorageType */ - storage?: string; + /** Storage location -- see CFB$StorageType */ + storage?: string; } /* File object */ -export interface CFBContainer { - /* list of streams and storages */ - FullPaths: string[]; +export interface CFB$Container { + /* List of streams and storages */ + FullPaths: string[]; - /* Array of entries in the same order as FullPaths */ - FileIndex: CFBEntry[]; + /* Array of entries in the same order as FullPaths */ + FileIndex: CFB$Entry[]; - /* Raw Content, in chunks (Buffer when available, Array of bytes otherwise) */ - raw?: { - header: CFB$Blob, - sectors: CFB$Blob[]; - }; + /* Raw Content, in chunks (Buffer when available, Array of bytes otherwise) */ + raw?: { + header: CFB$Blob, + sectors: CFB$Blob[]; + }; } /** General utilities */ export interface CFB$Utils { - cfb_new(opts?: any): CFBContainer; - cfb_add(cfb: CFBContainer, name: string, content: any, opts?: any): CFBEntry; - cfb_del(cfb: CFBContainer, name: string): boolean; - cfb_mov(cfb: CFBContainer, old_name: string, new_name: string): boolean; - cfb_gc(cfb: CFBContainer): void; - 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; + cfb_new(opts?: any): CFB$Container; + cfb_add(cfb: CFB$Container, name: string, content: any, opts?: any): CFB$Entry; + cfb_del(cfb: CFB$Container, name: string): boolean; + cfb_mov(cfb: CFB$Container, old_name: string, new_name: string): boolean; + cfb_gc(cfb: CFB$Container): void; + 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/xlscfb.flow.js b/xlscfb.flow.js index 8700f2a..b9d8bbe 100644 --- a/xlscfb.flow.js +++ b/xlscfb.flow.js @@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry}; /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/; -exports.version = '1.0.2'; +exports.version = '1.0.3'; /* [MS-CFB] 2.6.4 */ function namecmp(l/*:string*/, r/*:string*/)/*:number*/ { var L = l.split("/"), R = r.split("/"); @@ -353,14 +353,14 @@ function read_directory(dir_start/*:number*/, sector_list/*:SectorList*/, sector 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)/*:any*/); - prep_blob(o.content, 0); } else { o.storage = 'minifat'; - if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); - prep_blob(o.content, 0); } } + if(o.content) prep_blob(o.content, 0); files[name] = o; FileIndex.push(o); } diff --git a/xlscfb.js b/xlscfb.js index e3fd9f9..f1612a9 100644 --- a/xlscfb.js +++ b/xlscfb.js @@ -8,7 +8,7 @@ var DO_NOT_EXPORT_CFB = true; /* [MS-CFB] v20130118 */ var CFB = (function _CFB(){ var exports = {}; -exports.version = '1.0.2'; +exports.version = '1.0.3'; /* [MS-CFB] 2.6.4 */ function namecmp(l, r) { var L = l.split("/"), R = r.split("/"); @@ -323,14 +323,14 @@ function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, Fil 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 && sector_list[minifat_store]) { + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); - prep_blob(o.content, 0); } } + if(o.content) prep_blob(o.content, 0); files[name] = o; FileIndex.push(o); }