2017-07-28 17:53:08 +00:00
|
|
|
function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
|
2014-06-24 04:00:39 +00:00
|
|
|
var mver = 3; // major version
|
|
|
|
var ssz = 512; // sector size
|
|
|
|
var nmfs = 0; // number of mini FAT sectors
|
|
|
|
var ndfs = 0; // number of DIFAT sectors
|
|
|
|
var dir_start = 0; // first directory sector location
|
|
|
|
var minifat_start = 0; // first mini FAT sector location
|
|
|
|
var difat_start = 0; // first mini FAT sector location
|
|
|
|
|
2017-07-28 17:53:08 +00:00
|
|
|
var fat_addrs/*:Array<number>*/ = []; // locations of FAT sectors
|
2014-06-24 04:00:39 +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)*/;
|
2014-06-24 04:00:39 +00:00
|
|
|
prep_blob(blob, 0);
|
|
|
|
|
|
|
|
/* major version */
|
2014-11-03 04:02:42 +00:00
|
|
|
var mv = check_get_mver(blob);
|
|
|
|
mver = mv[0];
|
2014-06-24 04:00:39 +00:00
|
|
|
switch(mver) {
|
|
|
|
case 3: ssz = 512; break; case 4: ssz = 4096; break;
|
2017-03-30 21:34:37 +00:00
|
|
|
default: throw new Error("Major Version: Expected 3 or 4 saw " + mver);
|
2014-06-24 04:00:39 +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 */); }
|
2014-06-24 04:00:39 +00:00
|
|
|
/* Save header for final object */
|
2017-07-28 17:53:08 +00:00
|
|
|
var header/*:RawBytes*/ = file.slice(0,ssz);
|
2014-06-24 04:00:39 +00:00
|
|
|
|
|
|
|
check_shifts(blob, mver);
|
|
|
|
|
|
|
|
// Number of Directory Sectors
|
2017-07-28 17:53:08 +00:00
|
|
|
var nds/*:number*/ = blob.read_shift(4, 'i');
|
2017-03-30 21:34:37 +00:00
|
|
|
if(mver === 3 && nds !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + nds);
|
2014-06-24 04:00:39 +00:00
|
|
|
|
|
|
|
// Number of FAT Sectors
|
|
|
|
//var nfs = blob.read_shift(4, 'i');
|
|
|
|
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
|
|
|
|
ndfs = blob.read_shift(4, 'i');
|
|
|
|
|
|
|
|
// 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; */
|
2014-06-24 04:00:39 +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);
|
2014-06-24 04:00:39 +00:00
|
|
|
|
|
|
|
sleuth_fat(difat_start, ndfs, sectors, ssz, fat_addrs);
|
|
|
|
|
|
|
|
/** Chains */
|
2017-02-24 05:11:45 +00:00
|
|
|
var sector_list/*:SectorList*/ = make_sector_list(sectors, dir_start, fat_addrs, ssz);
|
2014-06-24 04:00:39 +00:00
|
|
|
|
|
|
|
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";
|
2014-11-03 04:02:42 +00:00
|
|
|
sector_list.fat_addrs = fat_addrs;
|
|
|
|
sector_list.ssz = ssz;
|
2014-06-24 04:00:39 +00:00
|
|
|
|
|
|
|
/* [MS-CFB] 2.6.1 Compound File Directory Entry */
|
2017-07-28 17:53:08 +00:00
|
|
|
var files/*:CFBFiles*/ = {}, Paths/*:Array<string>*/ = [], FileIndex/*:CFBFileIndex*/ = [], FullPaths/*:Array<string>*/ = [], FullPathDir = {};
|
2014-06-24 04:00:39 +00:00
|
|
|
read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex);
|
|
|
|
|
|
|
|
build_full_paths(FileIndex, FullPathDir, FullPaths, Paths);
|
|
|
|
|
2017-07-28 17:53:08 +00:00
|
|
|
var root_name/*:string*/ = Paths.shift();
|
2014-06-24 04:00:39 +00:00
|
|
|
|
|
|
|
/* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */
|
|
|
|
var find_path = make_find_path(FullPaths, Paths, FileIndex, files, root_name);
|
|
|
|
|
|
|
|
return {
|
|
|
|
raw: {header: header, sectors: sectors},
|
|
|
|
FileIndex: FileIndex,
|
|
|
|
FullPaths: FullPaths,
|
|
|
|
FullPathDir: FullPathDir,
|
|
|
|
find: find_path
|
|
|
|
};
|
|
|
|
} // parse
|
|
|
|
|