2017-02-24 05:11:45 +00:00
/* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*jshint eqnull:true */
2017-09-14 21:14:22 +00:00
/*exported CFB */
2018-09-04 07:14:20 +00:00
/*global module, require:false, process:false, Buffer:false, Uint8Array:false, Uint16Array:false */
2017-02-24 05:11:45 +00:00
2017-09-14 21:14:22 +00:00
var Base64 = ( function make _b64 ( ) {
2017-02-24 05:11:45 +00:00
var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;
return {
2017-09-14 21:14:22 +00:00
encode : function ( input /*:string*/ ) /*:string*/ {
var o = "" ;
2018-03-05 03:49:40 +00:00
var c1 = 0 , c2 = 0 , c3 = 0 , e1 = 0 , e2 = 0 , e3 = 0 , e4 = 0 ;
2017-09-14 21:14:22 +00:00
for ( var i = 0 ; i < input . length ; ) {
c1 = input . charCodeAt ( i ++ ) ;
e1 = ( c1 >> 2 ) ;
c2 = input . charCodeAt ( i ++ ) ;
e2 = ( ( c1 & 3 ) << 4 ) | ( c2 >> 4 ) ;
c3 = input . charCodeAt ( i ++ ) ;
e3 = ( ( c2 & 15 ) << 2 ) | ( c3 >> 6 ) ;
e4 = ( c3 & 63 ) ;
if ( isNaN ( c2 ) ) { e3 = e4 = 64 ; }
else if ( isNaN ( c3 ) ) { e4 = 64 ; }
o += map . charAt ( e1 ) + map . charAt ( e2 ) + map . charAt ( e3 ) + map . charAt ( e4 ) ;
}
return o ;
} ,
decode : function b64 _decode ( input /*:string*/ ) /*:string*/ {
2017-02-24 05:11:45 +00:00
var o = "" ;
2018-03-05 03:49:40 +00:00
var c1 = 0 , c2 = 0 , c3 = 0 , e1 = 0 , e2 = 0 , e3 = 0 , e4 = 0 ;
2017-02-24 05:11:45 +00:00
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 ;
}
} ;
} ) ( ) ;
2017-09-14 21:14:22 +00:00
var has _buf = ( typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process . versions !== 'undefined' && process . versions . node ) ;
2017-02-24 05:11:45 +00:00
2018-07-08 08:08:15 +00:00
var Buffer _from = /*::(*/ function ( ) { } /*:: :any)*/ ;
2018-04-28 17:52:41 +00:00
if ( typeof Buffer !== 'undefined' ) {
2018-07-08 08:08:15 +00:00
var nbfs = ! Buffer . from ;
if ( ! nbfs ) try { Buffer . from ( "foo" , "utf8" ) ; } catch ( e ) { nbfs = true ; }
2018-09-04 07:14:20 +00:00
Buffer _from = /*::((*/ nbfs ? function ( buf , enc ) { return ( enc ) ? new Buffer ( buf , enc ) : new Buffer ( buf ) ; } : Buffer . from . bind ( Buffer ) /*::) :any)*/ ;
2018-04-28 17:52:41 +00:00
// $FlowIgnore
if ( ! Buffer . alloc ) Buffer . alloc = function ( n ) { return new Buffer ( n ) ; } ;
2018-09-04 07:14:20 +00:00
// $FlowIgnore
if ( ! Buffer . allocUnsafe ) Buffer . allocUnsafe = function ( n ) { return new Buffer ( n ) ; } ;
2018-04-28 17:52:41 +00:00
}
2017-09-14 21:14:22 +00:00
function new _raw _buf ( len /*:number*/ ) {
/* jshint -W056 */
2018-04-28 17:52:41 +00:00
return has _buf ? Buffer . alloc ( len ) : new Array ( len ) ;
2017-09-14 21:14:22 +00:00
/* jshint +W056 */
}
2018-09-04 07:14:20 +00:00
function new _unsafe _buf ( len /*:number*/ ) {
/* jshint -W056 */
return has _buf ? Buffer . allocUnsafe ( len ) : new Array ( len ) ;
/* jshint +W056 */
}
var s2a = function s2a ( s /*:string*/ ) /*:any*/ {
if ( has _buf ) return Buffer _from ( s , "binary" ) ;
2018-07-08 08:08:15 +00:00
return s . split ( "" ) . map ( function ( x /*:string*/ ) /*:number*/ { return x . charCodeAt ( 0 ) & 0xff ; } ) ;
2017-09-14 21:14:22 +00:00
} ;
2017-02-24 05:11:45 +00:00
2017-11-27 05:41:39 +00:00
var chr0 = /\u0000/g , chr1 = /[\u0001-\u0006]/g ;
2017-07-28 17:53:08 +00:00
var _ _toBuffer = function ( bufs /*:Array<Array<RawBytes> >*/ ) /*:RawBytes*/ { var x = [ ] ; for ( var i = 0 ; i < bufs [ 0 ] . length ; ++ i ) { x . push . apply ( x , bufs [ 0 ] [ i ] ) ; } return x ; } ;
var _ _ _toBuffer = _ _toBuffer ;
2017-09-14 21:14:22 +00:00
var _ _utf16le = function ( b /*:RawBytes|CFBlob*/ , s /*:number*/ , e /*:number*/ ) /*:string*/ { var ss /*:Array<string>*/ = [ ] ; for ( var i = s ; i < e ; i += 2 ) ss . push ( String . fromCharCode ( _ _readUInt16LE ( b , i ) ) ) ; return ss . join ( "" ) . replace ( chr0 , '' ) ; } ;
2017-07-28 17:53:08 +00:00
var _ _ _utf16le = _ _utf16le ;
var _ _hexlify = function ( b /*:RawBytes|CFBlob*/ , s /*:number*/ , l /*:number*/ ) /*:string*/ { var ss /*:Array<string>*/ = [ ] ; for ( var i = s ; i < s + l ; ++ i ) ss . push ( ( "0" + b [ i ] . toString ( 16 ) ) . slice ( - 2 ) ) ; return ss . join ( "" ) ; } ;
var _ _ _hexlify = _ _hexlify ;
var _ _bconcat = function ( bufs /*:Array<RawBytes>*/ ) /*: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 ;
2017-02-24 05:11:45 +00:00
2017-09-14 21:14:22 +00:00
if ( has _buf /*:: && typeof Buffer !== 'undefined'*/ ) {
2017-07-28 17:53:08 +00:00
_ _utf16le = function ( b /*:RawBytes|CFBlob*/ , s /*:number*/ , e /*:number*/ ) /*:string*/ {
if ( ! Buffer . isBuffer ( b ) /*:: || !(b instanceof Buffer)*/ ) return _ _ _utf16le ( b , s , e ) ;
2017-09-14 21:14:22 +00:00
return b . toString ( 'utf16le' , s , e ) . replace ( chr0 , '' ) /*.replace(chr1,'!')*/ ;
2017-02-24 05:11:45 +00:00
} ;
2017-07-28 17:53:08 +00:00
_ _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<Array<RawBytes>>*/ ) /*:RawBytes*/ { return ( bufs [ 0 ] . length > 0 && Buffer . isBuffer ( bufs [ 0 ] [ 0 ] ) ) ? Buffer . concat ( ( bufs [ 0 ] /*:any*/ ) ) : _ _ _toBuffer ( bufs ) ; } ;
2018-07-08 08:08:15 +00:00
s2a = function ( s /*:string*/ ) /*:RawBytes*/ { return Buffer _from ( s , "binary" ) ; } ;
2017-07-28 17:53:08 +00:00
bconcat = function ( bufs /*:Array<RawBytes>*/ ) /*:RawBytes*/ { return Buffer . isBuffer ( bufs [ 0 ] ) ? Buffer . concat ( /*::(*/ bufs /*:: :any)*/ ) : _ _bconcat ( bufs ) ; } ;
2017-02-24 05:11:45 +00:00
}
2017-07-28 17:53:08 +00:00
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 ] ; } ;
2017-02-24 05:11:45 +00:00
2017-07-28 17:53:08 +00:00
function ReadShift ( size /*:number*/ , t /*:?string*/ ) /*:number|string*/ {
var oI /*:: :number = 0*/ , oS /*:: :string = ""*/ , type = 0 ;
2017-02-24 05:11:45 +00:00
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 ) ;
}
2017-09-14 21:14:22 +00:00
this . l += size ; if ( type === 0 ) return oI ; return oS ;
}
var _ _writeUInt32LE = function ( b /*:RawBytes|CFBlob*/ , val /*:number*/ , idx /*:number*/ ) /*:void*/ { b [ idx ] = ( val & 0xFF ) ; b [ idx + 1 ] = ( ( val >>> 8 ) & 0xFF ) ; b [ idx + 2 ] = ( ( val >>> 16 ) & 0xFF ) ; b [ idx + 3 ] = ( ( val >>> 24 ) & 0xFF ) ; } ;
var _ _writeInt32LE = function ( b /*:RawBytes|CFBlob*/ , val /*:number*/ , idx /*:number*/ ) /*:void*/ { b [ idx ] = ( val & 0xFF ) ; b [ idx + 1 ] = ( ( val >> 8 ) & 0xFF ) ; b [ idx + 2 ] = ( ( val >> 16 ) & 0xFF ) ; b [ idx + 3 ] = ( ( val >> 24 ) & 0xFF ) ; } ;
function WriteShift ( t /*:number*/ , val /*:string|number*/ , f /*:?string*/ ) /*:any*/ {
var size = 0 , i = 0 ;
switch ( f ) {
case "hex" : for ( ; i < t ; ++ i ) {
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
this [ this . l ++ ] = parseInt ( val . slice ( 2 * i , 2 * i + 2 ) , 16 ) || 0 ;
} return this ;
case "utf16le" :
/*:: if(typeof val !== "string") throw new Error("unreachable"); */
var end /*:number*/ = this . l + t ;
for ( i = 0 ; i < Math . min ( val . length , t ) ; ++ i ) {
var cc = val . charCodeAt ( i ) ;
this [ this . l ++ ] = cc & 0xff ;
this [ this . l ++ ] = cc >> 8 ;
}
while ( this . l < end ) this [ this . l ++ ] = 0 ;
return this ;
}
/*:: if(typeof val !== "number") throw new Error("unreachable"); */
switch ( t ) {
case 1 : size = 1 ; this [ this . l ] = val & 0xFF ; break ;
case 2 : size = 2 ; this [ this . l ] = val & 0xFF ; val >>>= 8 ; this [ this . l + 1 ] = val & 0xFF ; break ;
case 4 : size = 4 ; _ _writeUInt32LE ( this , val , this . l ) ; break ;
case - 4 : size = 4 ; _ _writeInt32LE ( this , val , this . l ) ; break ;
}
this . l += size ; return this ;
2017-02-24 05:11:45 +00:00
}
2017-07-28 17:53:08 +00:00
function CheckField ( hexstr /*:string*/ , fld /*:string*/ ) /*:void*/ {
2017-02-24 05:11:45 +00:00
var m = _ _hexlify ( this , this . l , hexstr . length >> 1 ) ;
2017-03-30 21:34:37 +00:00
if ( m !== hexstr ) throw new Error ( fld + 'Expected ' + hexstr + ' saw ' + m ) ;
2017-02-24 05:11:45 +00:00
this . l += hexstr . length >> 1 ;
}
2017-07-28 17:53:08 +00:00
function prep _blob ( blob /*:CFBlob*/ , pos /*:number*/ ) /*:void*/ {
2017-02-24 05:11:45 +00:00
blob . l = pos ;
2017-07-28 17:53:08 +00:00
blob . read _shift = /*::(*/ ReadShift /*:: :any)*/ ;
2017-02-24 05:11:45 +00:00
blob . chk = CheckField ;
2017-09-14 21:14:22 +00:00
blob . write _shift = WriteShift ;
}
function new _buf ( sz /*:number*/ ) /*:any*/ {
var o /*:CFBlob*/ = ( new _raw _buf ( sz ) /*:any*/ ) ;
prep _blob ( o , 0 ) ;
return o ;
2017-02-24 05:11:45 +00:00
}
/ * : :
2017-07-28 17:53:08 +00:00
declare var DO _NOT _EXPORT _CFB : ? boolean ;
type SectorEntry = {
name ? : string ;
nodes ? : Array < number > ;
data : RawBytes ;
} ;
2017-02-24 05:11:45 +00:00
type SectorList = {
2017-07-28 17:53:08 +00:00
[ k : string | number ] : SectorEntry ;
2017-02-24 05:11:45 +00:00
name : ? string ;
2017-07-28 17:53:08 +00:00
fat _addrs : Array < number > ;
2017-02-24 05:11:45 +00:00
ssz : number ;
}
2017-07-28 17:53:08 +00:00
type CFBFiles = { [ n : string ] : CFBEntry } ;
2017-02-24 05:11:45 +00:00
* /
2018-09-04 07:14:20 +00:00
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
var CRC32 ;
( function ( factory ) {
/*jshint ignore:start */
/*eslint-disable */
factory ( CRC32 = { } ) ;
/*eslint-enable */
/*jshint ignore:end */
} ( function ( CRC32 ) {
CRC32 . version = '1.2.0' ;
/* see perf/crc32table.js */
/*global Int32Array */
function signed _crc _table ( ) /*:any*/ {
var c = 0 , table /*:Array<number>*/ = new Array ( 256 ) ;
for ( var n = 0 ; n != 256 ; ++ n ) {
c = n ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
c = ( ( c & 1 ) ? ( - 306674912 ^ ( c >>> 1 ) ) : ( c >>> 1 ) ) ;
table [ n ] = c ;
}
return typeof Int32Array !== 'undefined' ? new Int32Array ( table ) : table ;
}
var T = signed _crc _table ( ) ;
function crc32 _bstr ( bstr /*:string*/ , seed /*:number*/ ) /*:number*/ {
var C = seed ^ - 1 , L = bstr . length - 1 ;
for ( var i = 0 ; i < L ; ) {
C = ( C >>> 8 ) ^ T [ ( C ^ bstr . charCodeAt ( i ++ ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ bstr . charCodeAt ( i ++ ) ) & 0xFF ] ;
}
if ( i === L ) C = ( C >>> 8 ) ^ T [ ( C ^ bstr . charCodeAt ( i ) ) & 0xFF ] ;
return C ^ - 1 ;
}
function crc32 _buf ( buf /*:Uint8Array|Array<number>*/ , seed /*:number*/ ) /*:number*/ {
if ( buf . length > 10000 ) return crc32 _buf _8 ( buf , seed ) ;
var C = seed ^ - 1 , L = buf . length - 3 ;
for ( var i = 0 ; i < L ; ) {
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
}
while ( i < L + 3 ) C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
return C ^ - 1 ;
}
function crc32 _buf _8 ( buf /*:Uint8Array|Array<number>*/ , seed /*:number*/ ) /*:number*/ {
var C = seed ^ - 1 , L = buf . length - 7 ;
for ( var i = 0 ; i < L ; ) {
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
}
while ( i < L + 7 ) C = ( C >>> 8 ) ^ T [ ( C ^ buf [ i ++ ] ) & 0xFF ] ;
return C ^ - 1 ;
}
function crc32 _str ( str /*:string*/ , seed /*:number*/ ) /*:number*/ {
var C = seed ^ - 1 ;
for ( var i = 0 , L = str . length , c , d ; i < L ; ) {
c = str . charCodeAt ( i ++ ) ;
if ( c < 0x80 ) {
C = ( C >>> 8 ) ^ T [ ( C ^ c ) & 0xFF ] ;
} else if ( c < 0x800 ) {
C = ( C >>> 8 ) ^ T [ ( C ^ ( 192 | ( ( c >> 6 ) & 31 ) ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 128 | ( c & 63 ) ) ) & 0xFF ] ;
} else if ( c >= 0xD800 && c < 0xE000 ) {
c = ( c & 1023 ) + 64 ; d = str . charCodeAt ( i ++ ) & 1023 ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 240 | ( ( c >> 8 ) & 7 ) ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 128 | ( ( c >> 2 ) & 63 ) ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 128 | ( ( d >> 6 ) & 15 ) | ( ( c & 3 ) << 4 ) ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 128 | ( d & 63 ) ) ) & 0xFF ] ;
} else {
C = ( C >>> 8 ) ^ T [ ( C ^ ( 224 | ( ( c >> 12 ) & 15 ) ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 128 | ( ( c >> 6 ) & 63 ) ) ) & 0xFF ] ;
C = ( C >>> 8 ) ^ T [ ( C ^ ( 128 | ( c & 63 ) ) ) & 0xFF ] ;
}
}
return C ^ - 1 ;
}
CRC32 . table = T ;
CRC32 . bstr = crc32 _bstr ;
CRC32 . buf = crc32 _buf ;
CRC32 . str = crc32 _str ;
} ) ) ;
2018-03-05 03:49:40 +00:00
/* [MS-CFB] v20171201 */
2017-02-24 05:11:45 +00:00
var CFB = ( function _CFB ( ) {
2017-07-28 17:53:08 +00:00
var exports /*:CFBModule*/ = /*::(*/ { } /*:: :any)*/ ;
2019-08-04 18:42:11 +00:00
exports . version = '1.1.3' ;
2017-09-14 21:14:22 +00:00
/* [MS-CFB] 2.6.4 */
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 ;
if ( L [ i ] != R [ i ] ) return L [ i ] < R [ i ] ? - 1 : 1 ;
}
return L . length - R . length ;
}
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 /*: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 ) ;
}
2018-09-04 07:14:20 +00:00
/* -------------------------------------------------------------------------- */
/ * D O S D a t e f o r m a t :
high | YYYYYYYm . mmmddddd . HHHHHMMM . MMMSSSSS | low
add 1980 to stored year
stored second should be doubled
* /
/* write JS date to buf as a DOS date */
function write _dos _date ( buf /*:CFBlob*/ , date /*:Date|string*/ ) {
if ( typeof date === "string" ) date = new Date ( date ) ;
var hms /*:number*/ = date . getHours ( ) ;
hms = hms << 6 | date . getMinutes ( ) ;
hms = hms << 5 | ( date . getSeconds ( ) >>> 1 ) ;
buf . write _shift ( 2 , hms ) ;
var ymd /*:number*/ = ( date . getFullYear ( ) - 1980 ) ;
ymd = ymd << 4 | ( date . getMonth ( ) + 1 ) ;
ymd = ymd << 5 | date . getDate ( ) ;
buf . write _shift ( 2 , ymd ) ;
}
/* read four bytes from buf and interpret as a DOS date */
function parse _dos _date ( buf /*:CFBlob*/ ) /*:Date*/ {
var hms = buf . read _shift ( 2 ) & 0xFFFF ;
var ymd = buf . read _shift ( 2 ) & 0xFFFF ;
var val = new Date ( ) ;
var d = ymd & 0x1F ; ymd >>>= 5 ;
var m = ymd & 0x0F ; ymd >>>= 4 ;
val . setMilliseconds ( 0 ) ;
val . setFullYear ( ymd + 1980 ) ;
val . setMonth ( m - 1 ) ;
val . setDate ( d ) ;
var S = hms & 0x1F ; hms >>>= 5 ;
var M = hms & 0x3F ; hms >>>= 6 ;
val . setHours ( hms ) ;
val . setMinutes ( M ) ;
val . setSeconds ( S << 1 ) ;
return val ;
}
function parse _extra _field ( blob /*:CFBlob*/ ) /*:any*/ {
prep _blob ( blob , 0 ) ;
var o = /*::(*/ { } /*:: :any)*/ ;
var flags = 0 ;
while ( blob . l <= blob . length - 4 ) {
var type = blob . read _shift ( 2 ) ;
var sz = blob . read _shift ( 2 ) , tgt = blob . l + sz ;
var p = { } ;
switch ( type ) {
/* UNIX-style Timestamps */
case 0x5455 : {
flags = blob . read _shift ( 1 ) ;
if ( flags & 1 ) p . mtime = blob . read _shift ( 4 ) ;
/* for some reason, CD flag corresponds to LFH */
if ( sz > 5 ) {
if ( flags & 2 ) p . atime = blob . read _shift ( 4 ) ;
if ( flags & 4 ) p . ctime = blob . read _shift ( 4 ) ;
}
if ( p . mtime ) p . mt = new Date ( p . mtime * 1000 ) ;
}
break ;
}
blob . l = tgt ;
o [ type ] = p ;
}
return o ;
}
2017-10-20 20:36:54 +00:00
var fs /*:: = require('fs'); */ ;
function get _fs ( ) { return fs || ( fs = require ( 'fs' ) ) ; }
2017-07-28 17:53:08 +00:00
function parse ( file /*:RawBytes*/ , options /*:CFBReadOpts*/ ) /*:CFBContainer*/ {
2018-09-04 07:14:20 +00:00
if ( file [ 0 ] == 0x50 && file [ 1 ] == 0x4b ) return parse _zip ( file , options ) ;
2018-03-05 03:49:40 +00:00
if ( file . length < 512 ) throw new Error ( "CFB file size " + file . length + " < 512" ) ;
2017-09-14 21:14:22 +00:00
var mver = 3 ;
var ssz = 512 ;
2017-02-24 05:11:45 +00:00
var nmfs = 0 ; // number of mini FAT sectors
2017-09-14 21:14:22 +00:00
var difat _sec _cnt = 0 ;
var dir _start = 0 ;
var minifat _start = 0 ;
var difat _start = 0 ;
2017-02-24 05:11:45 +00:00
2017-07-28 17:53:08 +00:00
var fat _addrs /*:Array<number>*/ = [ ] ; // locations of FAT sectors
2017-02-24 05:11:45 +00:00
/* [MS-CFB] 2.2 Compound File Header */
2017-07-28 17:53:08 +00:00
var blob /*:CFBlob*/ = /*::(*/ file . slice ( 0 , 512 ) /*:: :any)*/ ;
2017-02-24 05:11:45 +00:00
prep _blob ( blob , 0 ) ;
/* major version */
var mv = check _get _mver ( blob ) ;
mver = mv [ 0 ] ;
switch ( mver ) {
case 3 : ssz = 512 ; break ; case 4 : ssz = 4096 ; break ;
2018-09-04 07:14:20 +00:00
case 0 : if ( mv [ 1 ] == 0 ) return parse _zip ( file , options ) ;
/* falls through */
2017-03-30 21:34:37 +00:00
default : throw new Error ( "Major Version: Expected 3 or 4 saw " + mver ) ;
2017-02-24 05:11:45 +00:00
}
/* reprocess header */
2017-07-28 17:53:08 +00:00
if ( ssz !== 512 ) { blob = /*::(*/ file . slice ( 0 , ssz ) /*:: :any)*/ ; prep _blob ( blob , 28 /* blob.l */ ) ; }
2017-02-24 05:11:45 +00:00
/* Save header for final object */
2017-07-28 17:53:08 +00:00
var header /*:RawBytes*/ = file . slice ( 0 , ssz ) ;
2017-02-24 05:11:45 +00:00
check _shifts ( blob , mver ) ;
// Number of Directory Sectors
2017-09-14 21:14:22 +00:00
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 ) ;
2017-02-24 05:11:45 +00:00
// Number of FAT Sectors
blob . l += 4 ;
// First Directory Sector Location
dir _start = blob . read _shift ( 4 , 'i' ) ;
// Transaction Signature
blob . l += 4 ;
// Mini Stream Cutoff Size
blob . chk ( '00100000' , 'Mini Stream Cutoff Size: ' ) ;
// First Mini FAT Sector Location
minifat _start = blob . read _shift ( 4 , 'i' ) ;
// Number of Mini FAT Sectors
nmfs = blob . read _shift ( 4 , 'i' ) ;
// First DIFAT sector location
difat _start = blob . read _shift ( 4 , 'i' ) ;
// Number of DIFAT Sectors
2017-09-14 21:14:22 +00:00
difat _sec _cnt = blob . read _shift ( 4 , 'i' ) ;
2017-02-24 05:11:45 +00:00
// Grab FAT Sector Locations
2017-07-28 17:53:08 +00:00
for ( var q = - 1 , j = 0 ; j < 109 ; ++ j ) { /* 109 = (512 - blob.l)>>>2; */
2017-02-24 05:11:45 +00:00
q = blob . read _shift ( 4 , 'i' ) ;
if ( q < 0 ) break ;
fat _addrs [ j ] = q ;
}
/** Break the file up into sectors */
2017-07-28 17:53:08 +00:00
var sectors /*:Array<RawBytes>*/ = sectorify ( file , ssz ) ;
2017-02-24 05:11:45 +00:00
2017-09-14 21:14:22 +00:00
sleuth _fat ( difat _start , difat _sec _cnt , sectors , ssz , fat _addrs ) ;
2017-02-24 05:11:45 +00:00
/** Chains */
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" ;
sector _list [ fat _addrs [ 0 ] ] . name = "!FAT" ;
sector _list . fat _addrs = fat _addrs ;
sector _list . ssz = ssz ;
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
2017-11-05 00:15:50 +00:00
var files /*:CFBFiles*/ = { } , Paths /*:Array<string>*/ = [ ] , FileIndex /*:CFBFileIndex*/ = [ ] , FullPaths /*:Array<string>*/ = [ ] ;
2017-11-05 16:54:11 +00:00
read _directory ( dir _start , sector _list , sectors , Paths , nmfs , files , FileIndex , minifat _start ) ;
2017-02-24 05:11:45 +00:00
2017-11-05 00:15:50 +00:00
build _full _paths ( FileIndex , FullPaths , Paths ) ;
2017-09-14 21:14:22 +00:00
Paths . shift ( ) ;
2017-02-24 05:11:45 +00:00
2017-09-14 21:14:22 +00:00
var o = {
2017-02-24 05:11:45 +00:00
FileIndex : FileIndex ,
2017-11-05 00:15:50 +00:00
FullPaths : FullPaths
2017-02-24 05:11:45 +00:00
} ;
2017-09-14 21:14:22 +00:00
// $FlowIgnore
if ( options && options . raw ) o . raw = { header : header , sectors : sectors } ;
return o ;
2017-02-24 05:11:45 +00:00
} // parse
/* [MS-CFB] 2.2 Compound File Header -- read up to major version */
2017-07-28 17:53:08 +00:00
function check _get _mver ( blob /*:CFBlob*/ ) /*:[number, number]*/ {
2018-09-04 07:14:20 +00:00
if ( blob [ blob . l ] == 0x50 && blob [ blob . l + 1 ] == 0x4b ) return [ 0 , 0 ] ;
2017-02-24 05:11:45 +00:00
// header signature 8
blob . chk ( HEADER _SIGNATURE , 'Header Signature: ' ) ;
// clsid 16
2019-06-10 12:44:27 +00:00
//blob.chk(HEADER_CLSID, 'CLSID: ');
blob . l += 16 ;
2017-02-24 05:11:45 +00:00
// minor version 2
2017-07-28 17:53:08 +00:00
var mver /*:number*/ = blob . read _shift ( 2 , 'u' ) ;
2017-02-24 05:11:45 +00:00
return [ blob . read _shift ( 2 , 'u' ) , mver ] ;
}
2017-07-28 17:53:08 +00:00
function check _shifts ( blob /*:CFBlob*/ , mver /*:number*/ ) /*:void*/ {
2017-02-24 05:11:45 +00:00
var shift = 0x09 ;
// Byte Order
2017-03-30 21:34:37 +00:00
//blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff
blob . l += 2 ;
2017-02-24 05:11:45 +00:00
// Sector Shift
switch ( ( shift = blob . read _shift ( 2 ) ) ) {
2017-03-30 21:34:37 +00:00
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 ) ;
2017-02-24 05:11:45 +00:00
}
// Mini Sector Shift
blob . chk ( '0600' , 'Mini Sector Shift: ' ) ;
// Reserved
blob . chk ( '000000000000' , 'Reserved: ' ) ;
}
/** Break the file up into sectors */
2017-07-28 17:53:08 +00:00
function sectorify ( file /*:RawBytes*/ , ssz /*:number*/ ) /*:Array<RawBytes>*/ {
2017-02-24 05:11:45 +00:00
var nsectors = Math . ceil ( file . length / ssz ) - 1 ;
2017-07-28 17:53:08 +00:00
var sectors /*:Array<RawBytes>*/ = [ ] ;
2017-02-24 05:11:45 +00:00
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 */
2017-11-05 00:15:50 +00:00
function build _full _paths ( FI /*:CFBFileIndex*/ , FP /*:Array<string>*/ , Paths /*:Array<string>*/ ) /*:void*/ {
2017-02-24 05:11:45 +00:00
var i = 0 , L = 0 , R = 0 , C = 0 , j = 0 , pl = Paths . length ;
2017-07-28 17:53:08 +00:00
var dad /*:Array<number>*/ = [ ] , q /*:Array<number>*/ = [ ] ;
2017-02-24 05:11:45 +00:00
for ( ; i < pl ; ++ i ) { dad [ i ] = q [ i ] = i ; FP [ i ] = Paths [ i ] ; }
for ( ; j < q . length ; ++ j ) {
i = q [ j ] ;
L = FI [ i ] . L ; R = FI [ i ] . R ; C = FI [ i ] . C ;
if ( dad [ i ] === i ) {
if ( L !== - 1 /*NOSTREAM*/ && dad [ L ] !== L ) dad [ i ] = dad [ L ] ;
if ( R !== - 1 && dad [ R ] !== R ) dad [ i ] = dad [ R ] ;
}
if ( C !== - 1 /*NOSTREAM*/ ) dad [ C ] = i ;
2019-07-20 22:10:48 +00:00
if ( L !== - 1 && i != dad [ i ] ) { dad [ L ] = dad [ i ] ; if ( q . lastIndexOf ( L ) < j ) q . push ( L ) ; }
if ( R !== - 1 && i != dad [ i ] ) { dad [ R ] = dad [ i ] ; if ( q . lastIndexOf ( R ) < j ) q . push ( R ) ; }
2017-02-24 05:11:45 +00:00
}
2018-03-05 03:49:40 +00:00
for ( i = 1 ; i < pl ; ++ i ) if ( dad [ i ] === i ) {
2017-02-24 05:11:45 +00:00
if ( R !== - 1 /*NOSTREAM*/ && dad [ R ] !== R ) dad [ i ] = dad [ R ] ;
else if ( L !== - 1 && dad [ L ] !== L ) dad [ i ] = dad [ L ] ;
}
for ( i = 1 ; i < pl ; ++ i ) {
if ( FI [ i ] . type === 0 /* unknown */ ) continue ;
2018-12-12 18:50:04 +00:00
j = i ;
2019-07-20 22:10:48 +00:00
if ( j != dad [ j ] ) do {
2017-02-24 05:11:45 +00:00
j = dad [ j ] ;
2018-12-12 18:50:04 +00:00
FP [ i ] = FP [ j ] + "/" + FP [ i ] ;
2019-07-20 22:10:48 +00:00
} while ( j !== 0 && - 1 !== dad [ j ] && j != dad [ j ] ) ;
2018-12-12 18:50:04 +00:00
dad [ i ] = - 1 ;
2017-02-24 05:11:45 +00:00
}
FP [ 0 ] += "/" ;
for ( i = 1 ; i < pl ; ++ i ) {
if ( FI [ i ] . type !== 2 /* stream */ ) FP [ i ] += "/" ;
}
}
2017-11-05 16:54:11 +00:00
function get _mfat _entry ( entry /*:CFBEntry*/ , payload /*:RawBytes*/ , mini /*:?RawBytes*/ ) /*:CFBlob*/ {
var start = entry . start , size = entry . size ;
//return (payload.slice(start*MSSZ, start*MSSZ + size)/*:any*/);
var o = [ ] ;
var idx = start ;
while ( mini && size > 0 && idx >= 0 ) {
o . push ( payload . slice ( idx * MSSZ , idx * MSSZ + MSSZ ) ) ;
size -= MSSZ ;
idx = _ _readInt32LE ( mini , idx * 4 ) ;
}
if ( o . length === 0 ) return ( new _buf ( 0 ) /*:any*/ ) ;
return ( bconcat ( o ) . slice ( 0 , entry . size ) /*:any*/ ) ;
}
2017-02-24 05:11:45 +00:00
/ * * C h a s e d o w n t h e r e s t o f t h e D I F A T c h a i n t o b u i l d a c o m p r e h e n s i v e l i s t
2017-09-14 21:14:22 +00:00
DIFAT chains by storing the next sector number as the last 32 bits * /
2017-07-28 17:53:08 +00:00
function sleuth _fat ( idx /*:number*/ , cnt /*:number*/ , sectors /*:Array<RawBytes>*/ , ssz /*:number*/ , fat _addrs ) /*:void*/ {
var q /*:number*/ = ENDOFCHAIN ;
2017-02-24 05:11:45 +00:00
if ( idx === ENDOFCHAIN ) {
2017-03-30 21:34:37 +00:00
if ( cnt !== 0 ) throw new Error ( "DIFAT chain shorter than expected" ) ;
2017-02-24 05:11:45 +00:00
} else if ( idx !== - 1 /*FREESECT*/ ) {
var sector = sectors [ idx ] , m = ( ssz >>> 2 ) - 1 ;
if ( ! sector ) return ;
for ( var i = 0 ; i < m ; ++ i ) {
if ( ( q = _ _readInt32LE ( sector , i * 4 ) ) === ENDOFCHAIN ) break ;
fat _addrs . push ( q ) ;
}
sleuth _fat ( _ _readInt32LE ( sector , ssz - 4 ) , cnt - 1 , sectors , ssz , fat _addrs ) ;
}
}
/** Follow the linked list of sectors for a given starting point */
2017-07-28 17:53:08 +00:00
function get _sector _list ( sectors /*:Array<RawBytes>*/ , start /*:number*/ , fat _addrs /*:Array<number>*/ , ssz /*:number*/ , chkd /*:?Array<boolean>*/ ) /*:SectorEntry*/ {
var buf /*:Array<number>*/ = [ ] , buf _chain /*:Array<any>*/ = [ ] ;
if ( ! chkd ) chkd = [ ] ;
var modulus = ssz - 1 , j = 0 , jj = 0 ;
2017-02-24 05:11:45 +00:00
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 ) ;
2017-03-30 21:34:37 +00:00
if ( ssz < 4 + jj ) throw new Error ( "FAT boundary crossed: " + j + " 4 " + ssz ) ;
2017-02-24 05:11:45 +00:00
if ( ! sectors [ addr ] ) break ;
j = _ _readInt32LE ( sectors [ addr ] , jj ) ;
}
return { nodes : buf , data : _ _toBuffer ( [ buf _chain ] ) } ;
}
/** Chase down the sector linked lists */
2017-07-28 17:53:08 +00:00
function make _sector _list ( sectors /*:Array<RawBytes>*/ , dir _start /*:number*/ , fat _addrs /*:Array<number>*/ , ssz /*:number*/ ) /*:SectorList*/ {
var sl = sectors . length , sector _list /*:SectorList*/ = ( [ ] /*:any*/ ) ;
var chkd /*:Array<boolean>*/ = [ ] , buf /*:Array<number>*/ = [ ] , buf _chain /*:Array<RawBytes>*/ = [ ] ;
var modulus = ssz - 1 , i = 0 , j = 0 , k = 0 , jj = 0 ;
2017-02-24 05:11:45 +00:00
for ( i = 0 ; i < sl ; ++ i ) {
2017-07-28 17:53:08 +00:00
buf = ( [ ] /*:Array<number>*/ ) ;
2017-02-24 05:11:45 +00:00
k = ( i + dir _start ) ; if ( k >= sl ) k -= sl ;
2017-07-28 17:53:08 +00:00
if ( chkd [ k ] ) continue ;
2017-02-24 05:11:45 +00:00
buf _chain = [ ] ;
for ( j = k ; j >= 0 ; ) {
chkd [ j ] = true ;
buf [ buf . length ] = j ;
buf _chain . push ( sectors [ j ] ) ;
2017-07-28 17:53:08 +00:00
var addr /*:number*/ = fat _addrs [ Math . floor ( j * 4 / ssz ) ] ;
2017-02-24 05:11:45 +00:00
jj = ( ( j * 4 ) & modulus ) ;
2017-03-30 21:34:37 +00:00
if ( ssz < 4 + jj ) throw new Error ( "FAT boundary crossed: " + j + " 4 " + ssz ) ;
2017-02-24 05:11:45 +00:00
if ( ! sectors [ addr ] ) break ;
j = _ _readInt32LE ( sectors [ addr ] , jj ) ;
}
2017-07-28 17:53:08 +00:00
sector _list [ k ] = ( { nodes : buf , data : _ _toBuffer ( [ buf _chain ] ) } /*:SectorEntry*/ ) ;
2017-02-24 05:11:45 +00:00
}
return sector _list ;
}
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
2017-11-05 16:54:11 +00:00
function read _directory ( dir _start /*:number*/ , sector _list /*:SectorList*/ , sectors /*:Array<RawBytes>*/ , Paths /*:Array<string>*/ , nmfs , files , FileIndex , mini ) {
2017-02-24 05:11:45 +00:00
var minifat _store = 0 , pl = ( Paths . length ? 2 : 0 ) ;
var sector = sector _list [ dir _start ] . data ;
2017-07-28 17:53:08 +00:00
var i = 0 , namelen = 0 , name ;
2017-02-24 05:11:45 +00:00
for ( ; i < sector . length ; i += 128 ) {
2017-07-28 17:53:08 +00:00
var blob /*:CFBlob*/ = /*::(*/ sector . slice ( i , i + 128 ) /*:: :any)*/ ;
2017-02-24 05:11:45 +00:00
prep _blob ( blob , 64 ) ;
namelen = blob . read _shift ( 2 ) ;
name = _ _utf16le ( blob , 0 , namelen - pl ) ;
Paths . push ( name ) ;
2017-07-28 17:53:08 +00:00
var o /*:CFBEntry*/ = ( {
2017-02-24 05:11:45 +00:00
name : name ,
type : blob . read _shift ( 1 ) ,
color : blob . read _shift ( 1 ) ,
L : blob . read _shift ( 4 , 'i' ) ,
R : blob . read _shift ( 4 , 'i' ) ,
C : blob . read _shift ( 4 , 'i' ) ,
clsid : blob . read _shift ( 16 ) ,
2017-07-28 17:53:08 +00:00
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 ) ;
2017-02-24 05:11:45 +00:00
o . start = blob . read _shift ( 4 , 'i' ) ;
o . size = blob . read _shift ( 4 , 'i' ) ;
2017-08-09 06:50:59 +00:00
if ( o . size < 0 && o . start < 0 ) { o . size = o . type = 0 ; o . start = ENDOFCHAIN ; o . name = "" ; }
2017-02-24 05:11:45 +00:00
if ( o . type === 5 ) { /* root */
minifat _store = o . start ;
if ( nmfs > 0 && minifat _store !== ENDOFCHAIN ) sector _list [ minifat _store ] . name = "!StreamData" ;
/*minifat_size = o.size;*/
} else if ( o . size >= 4096 /* MSCSZ */ ) {
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 ;
2017-07-28 17:53:08 +00:00
o . content = ( sector _list [ o . start ] . data . slice ( 0 , o . size ) /*:any*/ ) ;
2017-02-24 05:11:45 +00:00
} else {
o . storage = 'minifat' ;
2018-02-12 07:30:44 +00:00
if ( o . size < 0 ) o . size = 0 ;
else if ( minifat _store !== ENDOFCHAIN && o . start !== ENDOFCHAIN && sector _list [ minifat _store ] ) {
2017-11-05 16:54:11 +00:00
o . content = get _mfat _entry ( o , sector _list [ minifat _store ] . data , ( sector _list [ mini ] || { } ) . data ) ;
2017-02-24 05:11:45 +00:00
}
}
2018-02-12 07:30:44 +00:00
if ( o . content ) prep _blob ( o . content , 0 ) ;
2017-02-24 05:11:45 +00:00
files [ name ] = o ;
FileIndex . push ( o ) ;
}
}
2017-07-28 17:53:08 +00:00
function read _date ( blob /*:RawBytes|CFBlob*/ , offset /*:number*/ ) /*:Date*/ {
2017-02-24 05:11:45 +00:00
return new Date ( ( ( ( _ _readUInt32LE ( blob , offset + 4 ) / 1e7 ) * Math . pow ( 2 , 32 ) + _ _readUInt32LE ( blob , offset ) / 1e7 ) - 11644473600 ) * 1000 ) ;
}
2017-09-14 21:14:22 +00:00
function read _file ( filename /*:string*/ , options /*:CFBReadOpts*/ ) {
2017-10-20 20:36:54 +00:00
get _fs ( ) ;
2017-02-24 05:11:45 +00:00
return parse ( fs . readFileSync ( filename ) , options ) ;
}
2017-09-14 21:14:22 +00:00
function read ( blob /*:RawBytes|string*/ , options /*:CFBReadOpts*/ ) {
2017-07-28 17:53:08 +00:00
switch ( options && options . type || "base64" ) {
2017-09-14 21:14:22 +00:00
case "file" : /*:: if(typeof blob !== 'string') throw "Must pass a filename when type='file'"; */ return read _file ( blob , options ) ;
2017-07-28 17:53:08 +00:00
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 ) ;
2017-02-24 05:11:45 +00:00
}
2017-07-28 17:53:08 +00:00
return parse ( /*::typeof blob == 'string' ? new Buffer(blob, 'utf-8') : */ blob , options ) ;
2017-02-24 05:11:45 +00:00
}
2017-09-14 21:14:22 +00:00
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 } /*:any*/ ) ;
}
if ( o . CLSID ) cfb . FileIndex [ 0 ] . clsid = o . CLSID ;
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 } /*:any*/ ) ) ;
cfb . FullPaths . push ( cfb . FullPaths [ 0 ] + nm ) ;
rebuild _cfb ( cfb ) ;
}
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 ) {
var _file = cfb . FileIndex [ i ] ;
switch ( _file . type ) {
case 0 :
if ( s ) gc = true ;
else { cfb . FileIndex . pop ( ) ; cfb . FullPaths . pop ( ) ; }
break ;
case 1 : case 2 : case 5 :
s = true ;
if ( isNaN ( _file . R * _file . L * _file . C ) ) gc = true ;
if ( _file . R > - 1 && _file . L > - 1 && _file . R == _file . L ) gc = true ;
break ;
default : gc = true ; break ;
}
}
if ( ! gc && ! f ) return ;
2017-09-20 23:33:03 +00:00
var now = new Date ( 1987 , 1 , 19 ) , j = 0 ;
2017-09-14 21:14:22 +00:00
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 ] ] ) ;
}
for ( i = 0 ; i < data . length ; ++ i ) {
var dad = dirname ( data [ i ] [ 0 ] ) ;
s = false ;
for ( j = 0 ; j < data . length ; ++ j ) if ( data [ j ] [ 0 ] === dad ) s = true ;
if ( ! s ) data . push ( [ dad , ( {
name : filename ( dad ) . replace ( "/" , "" ) ,
type : 1 ,
clsid : HEADER _CLSID ,
ct : now , mt : now ,
content : null
} /*:any*/ ) ] ) ;
}
data . sort ( function ( x , y ) { return namecmp ( x [ 0 ] , y [ 0 ] ) ; } ) ;
cfb . FullPaths = [ ] ; cfb . FileIndex = [ ] ;
for ( i = 0 ; i < data . length ; ++ i ) { cfb . FullPaths [ i ] = data [ i ] [ 0 ] ; cfb . FileIndex [ i ] = data [ i ] [ 1 ] ; }
for ( i = 0 ; i < data . length ; ++ i ) {
var elt = cfb . FileIndex [ i ] ;
var nm = cfb . FullPaths [ i ] ;
elt . name = filename ( nm ) . replace ( "/" , "" ) ;
elt . L = elt . R = elt . C = - ( elt . color = 1 ) ;
elt . size = elt . content ? elt . content . length : 0 ;
elt . start = 0 ;
elt . clsid = ( elt . clsid || HEADER _CLSID ) ;
if ( i === 0 ) {
elt . C = data . length > 1 ? 1 : - 1 ;
elt . size = 0 ;
elt . type = 5 ;
} else if ( nm . slice ( - 1 ) == "/" ) {
for ( j = i + 1 ; j < data . length ; ++ j ) if ( dirname ( cfb . FullPaths [ j ] ) == nm ) break ;
elt . C = j >= data . length ? - 1 : j ;
for ( j = i + 1 ; j < data . length ; ++ j ) if ( dirname ( cfb . FullPaths [ j ] ) == dirname ( nm ) ) break ;
elt . R = j >= data . length ? - 1 : j ;
elt . type = 1 ;
} else {
if ( dirname ( cfb . FullPaths [ i + 1 ] || "" ) == dirname ( nm ) ) elt . R = i + 1 ;
elt . type = 2 ;
}
}
}
function _write ( cfb /*:CFBContainer*/ , options /*:CFBWriteOpts*/ ) /*:RawBytes*/ {
2018-01-19 01:09:51 +00:00
var _opts = options || { } ;
2017-09-14 21:14:22 +00:00
rebuild _cfb ( cfb ) ;
2018-09-04 07:14:20 +00:00
if ( _opts . fileType == 'zip' ) return write _zip ( cfb , _opts ) ;
2017-09-14 21:14:22 +00:00
var L = ( function ( cfb /*:CFBContainer*/ ) /*:Array<number>*/ {
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 ;
/*:: if(file.content == null) throw new Error("unreachable"); */
var flen = file . content . length ;
2018-01-19 01:09:51 +00:00
if ( flen > 0 ) {
if ( flen < 0x1000 ) mini _size += ( flen + 0x3F ) >> 6 ;
else fat _size += ( flen + 0x01FF ) >> 9 ;
}
2017-09-14 21:14:22 +00:00
}
var dir _cnt = ( cfb . FullPaths . length + 3 ) >> 2 ;
var mini _cnt = ( mini _size + 7 ) >> 3 ;
var mfat _cnt = ( mini _size + 0x7F ) >> 7 ;
var fat _base = mini _cnt + fat _size + dir _cnt + mfat _cnt ;
var fat _cnt = ( fat _base + 0x7F ) >> 7 ;
var difat _cnt = fat _cnt <= 109 ? 0 : Math . ceil ( ( fat _cnt - 109 ) / 0x7F ) ;
while ( ( ( fat _base + fat _cnt + difat _cnt + 0x7F ) >> 7 ) > fat _cnt ) difat _cnt = ++ fat _cnt <= 109 ? 0 : Math . ceil ( ( fat _cnt - 109 ) / 0x7F ) ;
var L = [ 1 , difat _cnt , fat _cnt , mfat _cnt , dir _cnt , fat _size , mini _size , 0 ] ;
cfb . FileIndex [ 0 ] . size = mini _size << 6 ;
L [ 7 ] = ( cfb . FileIndex [ 0 ] . start = L [ 0 ] + L [ 1 ] + L [ 2 ] + L [ 3 ] + L [ 4 ] + L [ 5 ] ) + ( ( L [ 6 ] + 7 ) >> 3 ) ;
return L ;
} ) ( cfb ) ;
var o = new _buf ( L [ 7 ] << 9 ) ;
var i = 0 , T = 0 ;
{
for ( i = 0 ; i < 8 ; ++ i ) o . write _shift ( 1 , HEADER _SIG [ i ] ) ;
for ( i = 0 ; i < 8 ; ++ i ) o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , 0x003E ) ;
o . write _shift ( 2 , 0x0003 ) ;
o . write _shift ( 2 , 0xFFFE ) ;
o . write _shift ( 2 , 0x0009 ) ;
o . write _shift ( 2 , 0x0006 ) ;
for ( i = 0 ; i < 3 ; ++ i ) o . write _shift ( 2 , 0 ) ;
o . write _shift ( 4 , 0 ) ;
o . write _shift ( 4 , L [ 2 ] ) ;
o . write _shift ( 4 , L [ 0 ] + L [ 1 ] + L [ 2 ] + L [ 3 ] - 1 ) ;
o . write _shift ( 4 , 0 ) ;
o . write _shift ( 4 , 1 << 12 ) ;
o . write _shift ( 4 , L [ 3 ] ? L [ 0 ] + L [ 1 ] + L [ 2 ] - 1 : ENDOFCHAIN ) ;
o . write _shift ( 4 , L [ 3 ] ) ;
o . write _shift ( - 4 , L [ 1 ] ? L [ 0 ] - 1 : ENDOFCHAIN ) ;
o . write _shift ( 4 , L [ 1 ] ) ;
for ( i = 0 ; i < 109 ; ++ i ) o . write _shift ( - 4 , i < L [ 2 ] ? L [ 1 ] + i : - 1 ) ;
}
if ( L [ 1 ] ) {
for ( T = 0 ; T < L [ 1 ] ; ++ T ) {
for ( ; i < 236 + T * 127 ; ++ i ) o . write _shift ( - 4 , i < L [ 2 ] ? L [ 1 ] + i : - 1 ) ;
o . write _shift ( - 4 , T === L [ 1 ] - 1 ? ENDOFCHAIN : T + 1 ) ;
}
}
var chainit = function ( w /*:number*/ ) /*:void*/ {
for ( T += w ; i < T - 1 ; ++ i ) o . write _shift ( - 4 , i + 1 ) ;
if ( w ) { ++ i ; o . write _shift ( - 4 , ENDOFCHAIN ) ; }
} ;
T = i = 0 ;
for ( T += L [ 1 ] ; i < T ; ++ i ) o . write _shift ( - 4 , consts . DIFSECT ) ;
for ( T += L [ 2 ] ; i < T ; ++ i ) o . write _shift ( - 4 , consts . FATSECT ) ;
chainit ( L [ 3 ] ) ;
chainit ( L [ 4 ] ) ;
var j /*:number*/ = 0 , flen /*:number*/ = 0 ;
var file /*:CFBEntry*/ = cfb . FileIndex [ 0 ] ;
for ( ; j < cfb . FileIndex . length ; ++ j ) {
file = cfb . FileIndex [ j ] ;
if ( ! file . content ) continue ;
/*:: if(file.content == null) throw new Error("unreachable"); */
flen = file . content . length ;
if ( flen < 0x1000 ) continue ;
file . start = T ;
chainit ( ( flen + 0x01FF ) >> 9 ) ;
}
chainit ( ( L [ 6 ] + 7 ) >> 3 ) ;
while ( o . l & 0x1FF ) o . write _shift ( - 4 , consts . ENDOFCHAIN ) ;
T = i = 0 ;
for ( j = 0 ; j < cfb . FileIndex . length ; ++ j ) {
file = cfb . FileIndex [ j ] ;
if ( ! file . content ) continue ;
/*:: if(file.content == null) throw new Error("unreachable"); */
flen = file . content . length ;
if ( ! flen || flen >= 0x1000 ) continue ;
file . start = T ;
chainit ( ( flen + 0x3F ) >> 6 ) ;
}
while ( o . l & 0x1FF ) o . write _shift ( - 4 , consts . ENDOFCHAIN ) ;
for ( i = 0 ; i < L [ 4 ] << 2 ; ++ i ) {
var nm = cfb . FullPaths [ i ] ;
if ( ! nm || nm . length === 0 ) {
for ( j = 0 ; j < 17 ; ++ j ) o . write _shift ( 4 , 0 ) ;
for ( j = 0 ; j < 3 ; ++ j ) o . write _shift ( 4 , - 1 ) ;
for ( j = 0 ; j < 12 ; ++ j ) o . write _shift ( 4 , 0 ) ;
continue ;
}
file = cfb . FileIndex [ i ] ;
if ( i === 0 ) file . start = file . size ? file . start - 1 : ENDOFCHAIN ;
2018-01-19 01:09:51 +00:00
var _nm /*:string*/ = ( i === 0 && _opts . root ) || file . name ;
flen = 2 * ( _nm . length + 1 ) ;
o . write _shift ( 64 , _nm , "utf16le" ) ;
2017-09-14 21:14:22 +00:00
o . write _shift ( 2 , flen ) ;
o . write _shift ( 1 , file . type ) ;
o . write _shift ( 1 , file . color ) ;
o . write _shift ( - 4 , file . L ) ;
o . write _shift ( - 4 , file . R ) ;
o . write _shift ( - 4 , file . C ) ;
if ( ! file . clsid ) for ( j = 0 ; j < 4 ; ++ j ) o . write _shift ( 4 , 0 ) ;
else o . write _shift ( 16 , file . clsid , "hex" ) ;
o . write _shift ( 4 , file . state || 0 ) ;
o . write _shift ( 4 , 0 ) ; o . write _shift ( 4 , 0 ) ;
o . write _shift ( 4 , 0 ) ; o . write _shift ( 4 , 0 ) ;
o . write _shift ( 4 , file . start ) ;
o . write _shift ( 4 , file . size ) ; o . write _shift ( 4 , 0 ) ;
}
for ( i = 1 ; i < cfb . FileIndex . length ; ++ i ) {
file = cfb . FileIndex [ i ] ;
/*:: 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 ) ;
}
}
for ( i = 1 ; i < cfb . FileIndex . length ; ++ i ) {
file = cfb . FileIndex [ i ] ;
/*:: 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 ) ;
}
}
2017-09-20 23:33:03 +00:00
while ( o . l < o . length ) o . write _shift ( 1 , 0 ) ;
2017-09-14 21:14:22 +00:00
return o ;
}
/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
2017-08-09 06:50:59 +00:00
function find ( cfb /*:CFBContainer*/ , path /*:string*/ ) /*:?CFBEntry*/ {
2017-09-14 21:14:22 +00:00
var UCFullPaths /*:Array<string>*/ = cfb . FullPaths . map ( function ( x ) { return x . toUpperCase ( ) ; } ) ;
var UCPaths /*:Array<string>*/ = 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 /*:string*/ = path . toUpperCase ( ) ;
var w /*:number*/ = k === true ? UCFullPaths . indexOf ( UCPath ) : UCPaths . indexOf ( UCPath ) ;
if ( w !== - 1 ) return cfb . FileIndex [ w ] ;
2018-03-05 03:49:40 +00:00
var m = ! UCPath . match ( chr1 ) ;
UCPath = UCPath . replace ( chr0 , '' ) ;
if ( m ) UCPath = UCPath . replace ( chr1 , '!' ) ;
2017-09-14 21:14:22 +00:00
for ( w = 0 ; w < UCFullPaths . length ; ++ w ) {
2018-03-05 03:49:40 +00:00
if ( ( m ? UCFullPaths [ w ] . replace ( chr1 , '!' ) : UCFullPaths [ w ] ) . replace ( chr0 , '' ) == UCPath ) return cfb . FileIndex [ w ] ;
if ( ( m ? UCPaths [ w ] . replace ( chr1 , '!' ) : UCPaths [ w ] ) . replace ( chr0 , '' ) == UCPath ) return cfb . FileIndex [ w ] ;
2017-09-14 21:14:22 +00:00
}
return null ;
2017-08-09 06:50:59 +00:00
}
2017-02-24 05:11:45 +00:00
/** CFB Constants */
var MSSZ = 64 ; /* Mini Sector Size = 1<<6 */
//var MSCSZ = 4096; /* Mini Stream Cutoff Size */
/* 2.1 Compound File Sector Numbers and Types */
var ENDOFCHAIN = - 2 ;
/* 2.2 Compound File Header */
var HEADER _SIGNATURE = 'd0cf11e0a1b11ae1' ;
2017-09-14 21:14:22 +00:00
var HEADER _SIG = [ 0xD0 , 0xCF , 0x11 , 0xE0 , 0xA1 , 0xB1 , 0x1A , 0xE1 ] ;
2017-02-24 05:11:45 +00:00
var HEADER _CLSID = '00000000000000000000000000000000' ;
var consts = {
/* 2.1 Compund File Sector Numbers and Types */
MAXREGSECT : - 6 ,
DIFSECT : - 4 ,
FATSECT : - 3 ,
ENDOFCHAIN : ENDOFCHAIN ,
FREESECT : - 1 ,
/* 2.2 Compound File Header */
HEADER _SIGNATURE : HEADER _SIGNATURE ,
HEADER _MINOR _VERSION : '3e00' ,
MAXREGSID : - 6 ,
NOSTREAM : - 1 ,
HEADER _CLSID : HEADER _CLSID ,
/* 2.6.1 Compound File Directory Entry */
EntryTypes : [ 'unknown' , 'storage' , 'stream' , 'lockbytes' , 'property' , 'root' ]
} ;
2017-09-14 21:14:22 +00:00
function write _file ( cfb /*:CFBContainer*/ , filename /*:string*/ , options /*:CFBWriteOpts*/ ) /*:void*/ {
2017-10-20 20:36:54 +00:00
get _fs ( ) ;
2017-09-14 21:14:22 +00:00
var o = _write ( cfb , options ) ;
/*:: if(typeof Buffer == 'undefined' || !Buffer.isBuffer(o) || !(o instanceof Buffer)) throw new Error("unreachable"); */
fs . writeFileSync ( filename , 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 /*:CFBContainer*/ , options /*:CFBWriteOpts*/ ) /*:RawBytes|string*/ {
var o = _write ( cfb , options ) ;
switch ( options && options . type ) {
2017-10-20 20:36:54 +00:00
case "file" : get _fs ( ) ; fs . writeFileSync ( options . filename , ( o /*:any*/ ) ) ; return o ;
2017-09-14 21:14:22 +00:00
case "binary" : return a2s ( o ) ;
case "base64" : return Base64 . encode ( a2s ( o ) ) ;
}
return o ;
}
2018-09-04 07:14:20 +00:00
/* node < 8.1 zlib does not expose bytesRead, so default to pure JS */
var _zlib ;
function use _zlib ( zlib ) { try {
var InflateRaw = zlib . InflateRaw ;
var InflRaw = new InflateRaw ( ) ;
InflRaw . _processChunk ( new Uint8Array ( [ 3 , 0 ] ) , InflRaw . _finishFlushFlag ) ;
if ( InflRaw . bytesRead ) _zlib = zlib ;
else throw new Error ( "zlib does not expose bytesRead" ) ;
} catch ( e ) { console . error ( "cannot use native zlib: " + ( e . message || e ) ) ; } }
function _inflateRawSync ( payload , usz ) {
if ( ! _zlib ) return _inflate ( payload , usz ) ;
var InflateRaw = _zlib . InflateRaw ;
var InflRaw = new InflateRaw ( ) ;
var out = InflRaw . _processChunk ( payload . slice ( payload . l ) , InflRaw . _finishFlushFlag ) ;
payload . l += InflRaw . bytesRead ;
return out ;
}
function _deflateRawSync ( payload ) {
return _zlib ? _zlib . deflateRawSync ( payload ) : _deflate ( payload ) ;
}
var CLEN _ORDER = [ 16 , 17 , 18 , 0 , 8 , 7 , 9 , 6 , 10 , 5 , 11 , 4 , 12 , 3 , 13 , 2 , 14 , 1 , 15 ] ;
/* LEN_ID = [ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285 ]; */
var LEN _LN = [ 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 13 , 15 , 17 , 19 , 23 , 27 , 31 , 35 , 43 , 51 , 59 , 67 , 83 , 99 , 115 , 131 , 163 , 195 , 227 , 258 ] ;
/* DST_ID = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ]; */
var DST _LN = [ 1 , 2 , 3 , 4 , 5 , 7 , 9 , 13 , 17 , 25 , 33 , 49 , 65 , 97 , 129 , 193 , 257 , 385 , 513 , 769 , 1025 , 1537 , 2049 , 3073 , 4097 , 6145 , 8193 , 12289 , 16385 , 24577 ] ;
function bit _swap _8 ( n ) { var t = ( ( ( ( ( n << 1 ) | ( n << 11 ) ) & 0x22110 ) | ( ( ( n << 5 ) | ( n << 15 ) ) & 0x88440 ) ) ) ; return ( ( t >> 16 ) | ( t >> 8 ) | t ) & 0xFF ; }
var use _typed _arrays = typeof Uint8Array !== 'undefined' ;
var bitswap8 = use _typed _arrays ? new Uint8Array ( 1 << 8 ) : [ ] ;
for ( var q = 0 ; q < ( 1 << 8 ) ; ++ q ) bitswap8 [ q ] = bit _swap _8 ( q ) ;
function bit _swap _n ( n , b ) {
var rev = bitswap8 [ n & 0xFF ] ;
if ( b <= 8 ) return rev >>> ( 8 - b ) ;
rev = ( rev << 8 ) | bitswap8 [ ( n >> 8 ) & 0xFF ] ;
if ( b <= 16 ) return rev >>> ( 16 - b ) ;
rev = ( rev << 8 ) | bitswap8 [ ( n >> 16 ) & 0xFF ] ;
return rev >>> ( 24 - b ) ;
}
/* helpers for unaligned bit reads */
function read _bits _2 ( buf , bl ) { var w = ( bl & 7 ) , h = ( bl >>> 3 ) ; return ( ( buf [ h ] | ( w <= 6 ? 0 : buf [ h + 1 ] << 8 ) ) >>> w ) & 0x03 ; }
function read _bits _3 ( buf , bl ) { var w = ( bl & 7 ) , h = ( bl >>> 3 ) ; return ( ( buf [ h ] | ( w <= 5 ? 0 : buf [ h + 1 ] << 8 ) ) >>> w ) & 0x07 ; }
function read _bits _4 ( buf , bl ) { var w = ( bl & 7 ) , h = ( bl >>> 3 ) ; return ( ( buf [ h ] | ( w <= 4 ? 0 : buf [ h + 1 ] << 8 ) ) >>> w ) & 0x0F ; }
function read _bits _5 ( buf , bl ) { var w = ( bl & 7 ) , h = ( bl >>> 3 ) ; return ( ( buf [ h ] | ( w <= 3 ? 0 : buf [ h + 1 ] << 8 ) ) >>> w ) & 0x1F ; }
function read _bits _7 ( buf , bl ) { var w = ( bl & 7 ) , h = ( bl >>> 3 ) ; return ( ( buf [ h ] | ( w <= 1 ? 0 : buf [ h + 1 ] << 8 ) ) >>> w ) & 0x7F ; }
/* works up to n = 3 * 8 + 1 = 25 */
function read _bits _n ( buf , bl , n ) {
var w = ( bl & 7 ) , h = ( bl >>> 3 ) , f = ( ( 1 << n ) - 1 ) ;
var v = buf [ h ] >>> w ;
if ( n < 8 - w ) return v & f ;
v |= buf [ h + 1 ] << ( 8 - w ) ;
if ( n < 16 - w ) return v & f ;
v |= buf [ h + 2 ] << ( 16 - w ) ;
if ( n < 24 - w ) return v & f ;
v |= buf [ h + 3 ] << ( 24 - w ) ;
return v & f ;
}
/* until ArrayBuffer#realloc is a thing, fake a realloc */
function realloc ( b , sz /*:number*/ ) {
var L = b . length , M = 2 * L > sz ? 2 * L : sz + 5 , i = 0 ;
if ( L >= sz ) return b ;
if ( has _buf ) {
var o = new _unsafe _buf ( M ) ;
// $FlowIgnore
if ( b . copy ) b . copy ( o ) ;
else for ( ; i < b . length ; ++ i ) o [ i ] = b [ i ] ;
return o ;
} else if ( use _typed _arrays ) {
var a = new Uint8Array ( M ) ;
if ( a . set ) a . set ( b ) ;
else for ( ; i < b . length ; ++ i ) a [ i ] = b [ i ] ;
return a ;
}
b . length = M ;
return b ;
}
/* zero-filled arrays for older browsers */
function zero _fill _array ( n ) {
var o = new Array ( n ) ;
for ( var i = 0 ; i < n ; ++ i ) o [ i ] = 0 ;
return o ;
} var _deflate = ( function ( ) {
var _deflateRaw = ( function ( ) {
return function deflateRaw ( data , out ) {
var boff = 0 ;
while ( boff < data . length ) {
var L = Math . min ( 0xFFFF , data . length - boff ) ;
var h = boff + L == data . length ;
/* TODO: this is only type 0 stored */
out . write _shift ( 1 , + h ) ;
out . write _shift ( 2 , L ) ;
out . write _shift ( 2 , ( ~ L ) & 0xFFFF ) ;
while ( L -- > 0 ) out [ out . l ++ ] = data [ boff ++ ] ;
}
return out . l ;
} ;
} ) ( ) ;
return function ( data ) {
var buf = new _buf ( 50 + Math . floor ( data . length * 1.1 ) ) ;
var off = _deflateRaw ( data , buf ) ;
return buf . slice ( 0 , off ) ;
} ;
} ) ( ) ;
/* modified inflate function also moves original read head */
/* build tree (used for literals and lengths) */
function build _tree ( clens , cmap , MAX /*:number*/ ) /*:number*/ {
var maxlen = 1 , w = 0 , i = 0 , j = 0 , ccode = 0 , L = clens . length ;
var bl _count = use _typed _arrays ? new Uint16Array ( 32 ) : zero _fill _array ( 32 ) ;
for ( i = 0 ; i < 32 ; ++ i ) bl _count [ i ] = 0 ;
for ( i = L ; i < MAX ; ++ i ) clens [ i ] = 0 ;
L = clens . length ;
var ctree = use _typed _arrays ? new Uint16Array ( L ) : zero _fill _array ( L ) ; // []
/* build code tree */
for ( i = 0 ; i < L ; ++ i ) {
bl _count [ ( w = clens [ i ] ) ] ++ ;
if ( maxlen < w ) maxlen = w ;
ctree [ i ] = 0 ;
}
bl _count [ 0 ] = 0 ;
for ( i = 1 ; i <= maxlen ; ++ i ) bl _count [ i + 16 ] = ( ccode = ( ccode + bl _count [ i - 1 ] ) << 1 ) ;
for ( i = 0 ; i < L ; ++ i ) {
ccode = clens [ i ] ;
if ( ccode != 0 ) ctree [ i ] = bl _count [ ccode + 16 ] ++ ;
}
/* cmap[maxlen + 4 bits] = (off&15) + (lit<<4) reverse mapping */
var cleni = 0 ;
for ( i = 0 ; i < L ; ++ i ) {
cleni = clens [ i ] ;
if ( cleni != 0 ) {
ccode = bit _swap _n ( ctree [ i ] , maxlen ) >> ( maxlen - cleni ) ;
for ( j = ( 1 << ( maxlen + 4 - cleni ) ) - 1 ; j >= 0 ; -- j )
cmap [ ccode | ( j << cleni ) ] = ( cleni & 15 ) | ( i << 4 ) ;
}
}
return maxlen ;
}
var fix _lmap = use _typed _arrays ? new Uint16Array ( 512 ) : zero _fill _array ( 512 ) ;
var fix _dmap = use _typed _arrays ? new Uint16Array ( 32 ) : zero _fill _array ( 32 ) ;
if ( ! use _typed _arrays ) {
for ( var i = 0 ; i < 512 ; ++ i ) fix _lmap [ i ] = 0 ;
for ( i = 0 ; i < 32 ; ++ i ) fix _dmap [ i ] = 0 ;
}
( function ( ) {
var dlens /*:Array<number>*/ = [ ] ;
var i = 0 ;
for ( ; i < 32 ; i ++ ) dlens . push ( 5 ) ;
build _tree ( dlens , fix _dmap , 32 ) ;
var clens /*:Array<number>*/ = [ ] ;
i = 0 ;
for ( ; i <= 143 ; i ++ ) clens . push ( 8 ) ;
for ( ; i <= 255 ; i ++ ) clens . push ( 9 ) ;
for ( ; i <= 279 ; i ++ ) clens . push ( 7 ) ;
for ( ; i <= 287 ; i ++ ) clens . push ( 8 ) ;
build _tree ( clens , fix _lmap , 288 ) ;
} ) ( ) ;
var dyn _lmap = use _typed _arrays ? new Uint16Array ( 32768 ) : zero _fill _array ( 32768 ) ;
var dyn _dmap = use _typed _arrays ? new Uint16Array ( 32768 ) : zero _fill _array ( 32768 ) ;
var dyn _cmap = use _typed _arrays ? new Uint16Array ( 128 ) : zero _fill _array ( 128 ) ;
var dyn _len _1 = 1 , dyn _len _2 = 1 ;
/* 5.5.3 Expanding Huffman Codes */
function dyn ( data , boff /*:number*/ ) {
/* nomenclature from RFC1951 refers to bit values; these are offset by the implicit constant */
var _HLIT = read _bits _5 ( data , boff ) + 257 ; boff += 5 ;
var _HDIST = read _bits _5 ( data , boff ) + 1 ; boff += 5 ;
var _HCLEN = read _bits _4 ( data , boff ) + 4 ; boff += 4 ;
var w = 0 ;
/* grab and store code lengths */
var clens = use _typed _arrays ? new Uint8Array ( 19 ) : zero _fill _array ( 19 ) ;
var ctree = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ;
var maxlen = 1 ;
var bl _count = use _typed _arrays ? new Uint8Array ( 8 ) : zero _fill _array ( 8 ) ;
var next _code = use _typed _arrays ? new Uint8Array ( 8 ) : zero _fill _array ( 8 ) ;
var L = clens . length ; /* 19 */
for ( var i = 0 ; i < _HCLEN ; ++ i ) {
clens [ CLEN _ORDER [ i ] ] = w = read _bits _3 ( data , boff ) ;
if ( maxlen < w ) maxlen = w ;
bl _count [ w ] ++ ;
boff += 3 ;
}
/* build code tree */
var ccode = 0 ;
bl _count [ 0 ] = 0 ;
for ( i = 1 ; i <= maxlen ; ++ i ) next _code [ i ] = ccode = ( ccode + bl _count [ i - 1 ] ) << 1 ;
for ( i = 0 ; i < L ; ++ i ) if ( ( ccode = clens [ i ] ) != 0 ) ctree [ i ] = next _code [ ccode ] ++ ;
/* cmap[7 bits from stream] = (off&7) + (lit<<3) */
var cleni = 0 ;
for ( i = 0 ; i < L ; ++ i ) {
cleni = clens [ i ] ;
if ( cleni != 0 ) {
ccode = bitswap8 [ ctree [ i ] ] >> ( 8 - cleni ) ;
for ( var j = ( 1 << ( 7 - cleni ) ) - 1 ; j >= 0 ; -- j ) dyn _cmap [ ccode | ( j << cleni ) ] = ( cleni & 7 ) | ( i << 3 ) ;
}
}
/* read literal and dist codes at once */
var hcodes /*:Array<number>*/ = [ ] ;
maxlen = 1 ;
for ( ; hcodes . length < _HLIT + _HDIST ; ) {
ccode = dyn _cmap [ read _bits _7 ( data , boff ) ] ;
boff += ccode & 7 ;
switch ( ( ccode >>>= 3 ) ) {
case 16 :
w = 3 + read _bits _2 ( data , boff ) ; boff += 2 ;
ccode = hcodes [ hcodes . length - 1 ] ;
while ( w -- > 0 ) hcodes . push ( ccode ) ;
break ;
case 17 :
w = 3 + read _bits _3 ( data , boff ) ; boff += 3 ;
while ( w -- > 0 ) hcodes . push ( 0 ) ;
break ;
case 18 :
w = 11 + read _bits _7 ( data , boff ) ; boff += 7 ;
while ( w -- > 0 ) hcodes . push ( 0 ) ;
break ;
default :
hcodes . push ( ccode ) ;
if ( maxlen < ccode ) maxlen = ccode ;
break ;
}
}
/* build literal / length trees */
var h1 = hcodes . slice ( 0 , _HLIT ) , h2 = hcodes . slice ( _HLIT ) ;
for ( i = _HLIT ; i < 286 ; ++ i ) h1 [ i ] = 0 ;
for ( i = _HDIST ; i < 30 ; ++ i ) h2 [ i ] = 0 ;
dyn _len _1 = build _tree ( h1 , dyn _lmap , 286 ) ;
dyn _len _2 = build _tree ( h2 , dyn _dmap , 30 ) ;
return boff ;
}
/* return [ data, bytesRead ] */
function inflate ( data , usz /*:number*/ ) {
/* shortcircuit for empty buffer [0x03, 0x00] */
if ( data [ 0 ] == 3 && ! ( data [ 1 ] & 0x3 ) ) { return [ new _raw _buf ( usz ) , 2 ] ; }
/* bit offset */
var boff = 0 ;
/* header includes final bit and type bits */
var header = 0 ;
var outbuf = new _unsafe _buf ( usz ? usz : ( 1 << 18 ) ) ;
var woff = 0 ;
var OL = outbuf . length >>> 0 ;
var max _len _1 = 0 , max _len _2 = 0 ;
while ( ( header & 1 ) == 0 ) {
header = read _bits _3 ( data , boff ) ; boff += 3 ;
if ( ( header >>> 1 ) == 0 ) {
/* Stored block */
if ( boff & 7 ) boff += 8 - ( boff & 7 ) ;
/* 2 bytes sz, 2 bytes bit inverse */
var sz = data [ boff >>> 3 ] | data [ ( boff >>> 3 ) + 1 ] << 8 ;
boff += 32 ;
/* push sz bytes */
if ( ! usz && OL < woff + sz ) { outbuf = realloc ( outbuf , woff + sz ) ; OL = outbuf . length ; }
if ( typeof data . copy === 'function' ) {
// $FlowIgnore
data . copy ( outbuf , woff , boff >>> 3 , ( boff >>> 3 ) + sz ) ;
woff += sz ; boff += 8 * sz ;
} else while ( sz -- > 0 ) { outbuf [ woff ++ ] = data [ boff >>> 3 ] ; boff += 8 ; }
continue ;
} else if ( ( header >>> 1 ) == 1 ) {
/* Fixed Huffman */
max _len _1 = 9 ; max _len _2 = 5 ;
} else {
/* Dynamic Huffman */
boff = dyn ( data , boff ) ;
max _len _1 = dyn _len _1 ; max _len _2 = dyn _len _2 ;
}
if ( ! usz && ( OL < woff + 32767 ) ) { outbuf = realloc ( outbuf , woff + 32767 ) ; OL = outbuf . length ; }
for ( ; ; ) { // while(true) is apparently out of vogue in modern JS circles
/* ingest code and move read head */
var bits = read _bits _n ( data , boff , max _len _1 ) ;
var code = ( header >>> 1 ) == 1 ? fix _lmap [ bits ] : dyn _lmap [ bits ] ;
boff += code & 15 ; code >>>= 4 ;
/* 0-255 are literals, 256 is end of block token, 257+ are copy tokens */
if ( ( ( code >>> 8 ) & 0xFF ) === 0 ) outbuf [ woff ++ ] = code ;
else if ( code == 256 ) break ;
else {
code -= 257 ;
var len _eb = ( code < 8 ) ? 0 : ( ( code - 4 ) >> 2 ) ; if ( len _eb > 5 ) len _eb = 0 ;
var tgt = woff + LEN _LN [ code ] ;
/* length extra bits */
if ( len _eb > 0 ) {
tgt += read _bits _n ( data , boff , len _eb ) ;
boff += len _eb ;
}
/* dist code */
bits = read _bits _n ( data , boff , max _len _2 ) ;
code = ( header >>> 1 ) == 1 ? fix _dmap [ bits ] : dyn _dmap [ bits ] ;
boff += code & 15 ; code >>>= 4 ;
var dst _eb = ( code < 4 ? 0 : ( code - 2 ) >> 1 ) ;
var dst = DST _LN [ code ] ;
/* dist extra bits */
if ( dst _eb > 0 ) {
dst += read _bits _n ( data , boff , dst _eb ) ;
boff += dst _eb ;
}
/* in the common case, manual byte copy is faster than TA set / Buffer copy */
if ( ! usz && OL < tgt ) { outbuf = realloc ( outbuf , tgt ) ; OL = outbuf . length ; }
while ( woff < tgt ) { outbuf [ woff ] = outbuf [ woff - dst ] ; ++ woff ; }
}
}
}
return [ usz ? outbuf : outbuf . slice ( 0 , woff ) , ( boff + 7 ) >>> 3 ] ;
}
function _inflate ( payload , usz ) {
var data = payload . slice ( payload . l || 0 ) ;
var out = inflate ( data , usz ) ;
payload . l += out [ 1 ] ;
return out [ 0 ] ;
}
function warn _or _throw ( wrn , msg ) {
if ( wrn ) { if ( typeof console !== 'undefined' ) console . error ( msg ) ; }
else throw new Error ( msg ) ;
}
function parse _zip ( file /*:RawBytes*/ , options /*:CFBReadOpts*/ ) /*:CFBContainer*/ {
var blob /*:CFBlob*/ = /*::(*/ file /*:: :any)*/ ;
prep _blob ( blob , 0 ) ;
var FileIndex /*:CFBFileIndex*/ = [ ] , FullPaths /*:Array<string>*/ = [ ] ;
var o = {
FileIndex : FileIndex ,
FullPaths : FullPaths
} ;
init _cfb ( o , { root : options . root } ) ;
/* find end of central directory, start just after signature */
var i = blob . length - 4 ;
while ( ( blob [ i ] != 0x50 || blob [ i + 1 ] != 0x4b || blob [ i + 2 ] != 0x05 || blob [ i + 3 ] != 0x06 ) && i >= 0 ) -- i ;
blob . l = i + 4 ;
/* parse end of central directory */
blob . l += 4 ;
var fcnt = blob . read _shift ( 2 ) ;
blob . l += 6 ;
var start _cd = blob . read _shift ( 4 ) ;
/* parse central directory */
blob . l = start _cd ;
for ( i = 0 ; i < fcnt ; ++ i ) {
/* trust local file header instead of CD entry */
blob . l += 20 ;
var csz = blob . read _shift ( 4 ) ;
var usz = blob . read _shift ( 4 ) ;
var namelen = blob . read _shift ( 2 ) ;
var efsz = blob . read _shift ( 2 ) ;
var fcsz = blob . read _shift ( 2 ) ;
blob . l += 8 ;
var offset = blob . read _shift ( 4 ) ;
var EF = parse _extra _field ( /*::(*/ blob . slice ( blob . l + namelen , blob . l + namelen + efsz ) /*:: :any)*/ ) ;
blob . l += namelen + efsz + fcsz ;
var L = blob . l ;
blob . l = offset + 4 ;
parse _local _file ( blob , csz , usz , o , EF ) ;
blob . l = L ;
}
return o ;
}
/* head starts just after local file header signature */
function parse _local _file ( blob /*:CFBlob*/ , csz /*:number*/ , usz /*:number*/ , o /*:CFBContainer*/ , EF ) {
/* [local file header] */
blob . l += 2 ;
var flags = blob . read _shift ( 2 ) ;
var meth = blob . read _shift ( 2 ) ;
var date = parse _dos _date ( blob ) ;
if ( flags & 0x2041 ) throw new Error ( "Unsupported ZIP encryption" ) ;
var crc32 = blob . read _shift ( 4 ) ;
var _csz = blob . read _shift ( 4 ) ;
var _usz = blob . read _shift ( 4 ) ;
var namelen = blob . read _shift ( 2 ) ;
var efsz = blob . read _shift ( 2 ) ;
// TODO: flags & (1<<11) // UTF8
var name = "" ; for ( var i = 0 ; i < namelen ; ++ i ) name += String . fromCharCode ( blob [ blob . l ++ ] ) ;
if ( efsz ) {
var ef = parse _extra _field ( /*::(*/ blob . slice ( blob . l , blob . l + efsz ) /*:: :any)*/ ) ;
if ( ( ef [ 0x5455 ] || { } ) . mt ) date = ef [ 0x5455 ] . mt ;
if ( ( ( EF || { } ) [ 0x5455 ] || { } ) . mt ) date = EF [ 0x5455 ] . mt ;
}
blob . l += efsz ;
/* [encryption header] */
/* [file data] */
var data = blob . slice ( blob . l , blob . l + _csz ) ;
switch ( meth ) {
case 8 : data = _inflateRawSync ( blob , _usz ) ; break ;
case 0 : break ;
default : throw new Error ( "Unsupported ZIP Compression method " + meth ) ;
}
/* [data descriptor] */
var wrn = false ;
if ( flags & 8 ) {
crc32 = blob . read _shift ( 4 ) ;
if ( crc32 == 0x08074b50 ) { crc32 = blob . read _shift ( 4 ) ; wrn = true ; }
_csz = blob . read _shift ( 4 ) ;
_usz = blob . read _shift ( 4 ) ;
}
if ( _csz != csz ) warn _or _throw ( wrn , "Bad compressed size: " + csz + " != " + _csz ) ;
if ( _usz != usz ) warn _or _throw ( wrn , "Bad uncompressed size: " + usz + " != " + _usz ) ;
var _crc32 = CRC32 . buf ( data , 0 ) ;
2019-08-04 18:42:11 +00:00
if ( ( crc32 >> 0 ) != ( _crc32 >> 0 ) ) warn _or _throw ( wrn , "Bad CRC32 checksum: " + crc32 + " != " + _crc32 ) ;
2018-09-04 07:14:20 +00:00
cfb _add ( o , name , data , { unsafe : true , mt : date } ) ;
}
function write _zip ( cfb /*:CFBContainer*/ , options /*:CFBWriteOpts*/ ) /*:RawBytes*/ {
var _opts = options || { } ;
var out = [ ] , cdirs = [ ] ;
var o /*:CFBlob*/ = new _buf ( 1 ) ;
var method = ( _opts . compression ? 8 : 0 ) , flags = 0 ;
var desc = false ;
if ( desc ) flags |= 8 ;
var i = 0 , j = 0 ;
var start _cd = 0 , fcnt = 0 ;
var root = cfb . FullPaths [ 0 ] , fp = root , fi = cfb . FileIndex [ 0 ] ;
var crcs = [ ] ;
var sz _cd = 0 ;
for ( i = 1 ; i < cfb . FullPaths . length ; ++ i ) {
fp = cfb . FullPaths [ i ] . slice ( root . length ) ; fi = cfb . FileIndex [ i ] ;
if ( ! fi . size || ! fi . content || fp == "\u0001Sh33tJ5" ) continue ;
var start = start _cd ;
/* TODO: CP437 filename */
var namebuf = new _buf ( fp . length ) ;
for ( j = 0 ; j < fp . length ; ++ j ) namebuf . write _shift ( 1 , fp . charCodeAt ( j ) & 0x7F ) ;
namebuf = namebuf . slice ( 0 , namebuf . l ) ;
crcs [ fcnt ] = CRC32 . buf ( /*::((*/ fi . content /*::||[]):any)*/ , 0 ) ;
var outbuf = fi . content /*::||[]*/ ;
if ( method == 8 ) outbuf = _deflateRawSync ( outbuf ) ;
/* local file header */
o = new _buf ( 30 ) ;
o . write _shift ( 4 , 0x04034b50 ) ;
o . write _shift ( 2 , 20 ) ;
o . write _shift ( 2 , flags ) ;
o . write _shift ( 2 , method ) ;
/* TODO: last mod file time/date */
if ( fi . mt ) write _dos _date ( o , fi . mt ) ;
else o . write _shift ( 4 , 0 ) ;
o . write _shift ( - 4 , ( flags & 8 ) ? 0 : crcs [ fcnt ] ) ;
o . write _shift ( 4 , ( flags & 8 ) ? 0 : outbuf . length ) ;
o . write _shift ( 4 , ( flags & 8 ) ? 0 : /*::(*/ fi . content /*::||[])*/ . length ) ;
o . write _shift ( 2 , namebuf . length ) ;
o . write _shift ( 2 , 0 ) ;
start _cd += o . length ;
out . push ( o ) ;
start _cd += namebuf . length ;
out . push ( namebuf ) ;
/* TODO: encryption header ? */
start _cd += outbuf . length ;
out . push ( outbuf ) ;
/* data descriptor */
if ( flags & 8 ) {
o = new _buf ( 12 ) ;
o . write _shift ( - 4 , crcs [ fcnt ] ) ;
o . write _shift ( 4 , outbuf . length ) ;
o . write _shift ( 4 , /*::(*/ fi . content /*::||[])*/ . length ) ;
start _cd += o . l ;
out . push ( o ) ;
}
/* central directory */
o = new _buf ( 46 ) ;
o . write _shift ( 4 , 0x02014b50 ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , 20 ) ;
o . write _shift ( 2 , flags ) ;
o . write _shift ( 2 , method ) ;
o . write _shift ( 4 , 0 ) ; /* TODO: last mod file time/date */
o . write _shift ( - 4 , crcs [ fcnt ] ) ;
o . write _shift ( 4 , outbuf . length ) ;
o . write _shift ( 4 , /*::(*/ fi . content /*::||[])*/ . length ) ;
o . write _shift ( 2 , namebuf . length ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 4 , 0 ) ;
o . write _shift ( 4 , start ) ;
sz _cd += o . l ;
cdirs . push ( o ) ;
sz _cd += namebuf . length ;
cdirs . push ( namebuf ) ;
++ fcnt ;
}
/* end of central directory */
o = new _buf ( 22 ) ;
o . write _shift ( 4 , 0x06054b50 ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , 0 ) ;
o . write _shift ( 2 , fcnt ) ;
o . write _shift ( 2 , fcnt ) ;
o . write _shift ( 4 , sz _cd ) ;
o . write _shift ( 4 , start _cd ) ;
o . write _shift ( 2 , 0 ) ;
return bconcat ( ( [ bconcat ( ( out /*:any*/ ) ) , bconcat ( cdirs ) , o ] /*:any*/ ) ) ;
}
2017-09-14 21:14:22 +00:00
function cfb _new ( opts /*:?any*/ ) /*:CFBContainer*/ {
var o /*:CFBContainer*/ = ( { } /*:any*/ ) ;
init _cfb ( o , opts ) ;
return o ;
}
function cfb _add ( cfb /*:CFBContainer*/ , name /*:string*/ , content /*:?RawBytes*/ , opts /*:?any*/ ) /*:CFBEntry*/ {
2018-04-09 06:33:22 +00:00
var unsafe = opts && opts . unsafe ;
if ( ! unsafe ) init _cfb ( cfb ) ;
var file = ! unsafe && CFB . find ( cfb , name ) ;
2017-09-14 21:14:22 +00:00
if ( ! file ) {
2017-10-20 20:36:54 +00:00
var fpath /*:string*/ = cfb . FullPaths [ 0 ] ;
2017-09-20 23:33:03 +00:00
if ( name . slice ( 0 , fpath . length ) == fpath ) fpath = name ;
else {
if ( fpath . slice ( - 1 ) != "/" ) fpath += "/" ;
fpath = ( fpath + name ) . replace ( "//" , "/" ) ;
}
2017-10-20 20:36:54 +00:00
file = ( { name : filename ( name ) , type : 2 } /*:any*/ ) ;
2017-09-14 21:14:22 +00:00
cfb . FileIndex . push ( file ) ;
2017-09-20 23:33:03 +00:00
cfb . FullPaths . push ( fpath ) ;
2018-04-09 06:33:22 +00:00
if ( ! unsafe ) CFB . utils . cfb _gc ( cfb ) ;
2017-09-14 21:14:22 +00:00
}
/*:: 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 ;
2018-09-04 07:14:20 +00:00
if ( opts . mt ) file . mt = opts . mt ;
if ( opts . ct ) file . ct = opts . ct ;
2017-09-14 21:14:22 +00:00
}
return file ;
}
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 ) {
cfb . FileIndex . splice ( j , 1 ) ;
cfb . FullPaths . splice ( j , 1 ) ;
return true ;
}
return false ;
}
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 ) {
cfb . FileIndex [ j ] . name = filename ( new _name ) ;
cfb . FullPaths [ j ] = new _name ;
return true ;
}
return false ;
}
function cfb _gc ( cfb /*:CFBContainer*/ ) /*:void*/ { rebuild _cfb ( cfb , true ) ; }
2017-08-09 06:50:59 +00:00
exports . find = find ;
2017-09-14 21:14:22 +00:00
exports . read = read ;
2017-02-24 05:11:45 +00:00
exports . parse = parse ;
2017-09-14 21:14:22 +00:00
exports . write = write ;
exports . writeFile = write _file ;
2017-02-24 05:11:45 +00:00
exports . utils = {
2017-09-14 21:14:22 +00:00
cfb _new : cfb _new ,
cfb _add : cfb _add ,
cfb _del : cfb _del ,
cfb _mov : cfb _mov ,
cfb _gc : cfb _gc ,
2017-02-24 05:11:45 +00:00
ReadShift : ReadShift ,
CheckField : CheckField ,
prep _blob : prep _blob ,
bconcat : bconcat ,
2018-09-04 07:14:20 +00:00
use _zlib : use _zlib ,
_deflateRaw : _deflate ,
_inflateRaw : _inflate ,
2017-02-24 05:11:45 +00:00
consts : consts
} ;
return exports ;
} ) ( ) ;
if ( typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO _NOT _EXPORT _CFB === 'undefined' ) { module . exports = CFB ; }