Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make parser handle marshalling an un marshalling of external files #17

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions build/lib/fileref-data/fileref-data.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export declare class FilerefData {
systemName: string;
location: string;
format: string;
constructor(systemName: string, location: string, format: string);
getFileName(): string;
getDir(): string;
getLocation(delminator: string): string;
getSystemName(): string;
getFormat(): string;
setLocation(location: string): void;
}
export declare function unmarshall(stream: string): FilerefData;
export declare function marshall(data: FilerefData): string;
140 changes: 140 additions & 0 deletions build/lib/fileref-data/fileref-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var path_1 = __importDefault(require("path"));
var utils_1 = require("./utils");
var FilerefData = /** @class */ (function () {
function FilerefData(systemName, location, format) {
this.systemName = systemName;
this.location = location;
this.format = format;
}
FilerefData.prototype.getFileName = function () {
return path_1.default.parse(this.location).base;
};
FilerefData.prototype.getDir = function () {
return path_1.default.basename(path_1.default.dirname(this.location));
};
FilerefData.prototype.getLocation = function (delminator) {
return this.location.split(path_1.default.sep).join(delminator);
};
FilerefData.prototype.getSystemName = function () {
return this.systemName;
};
FilerefData.prototype.getFormat = function () {
return this.format;
};
FilerefData.prototype.setLocation = function (location) {
this.location = location;
};
return FilerefData;
}());
exports.FilerefData = FilerefData;
function unmarshall(stream) {
// Leave the first 8 as padding
var cntr = 8;
// 8 to 12 as the total length, 2 padding
var totalLength = utils_1.hex2dec(stream.substr(cntr, 4));
cntr += 6;
// 14 to 20 Unknown
cntr += 6;
// 20 to 22 length of System Name
var systemNameLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 2;
// Next 62 as System Name
var systemName = utils_1.hex2ascii(stream.substr(cntr, systemNameLength * 2));
cntr += 62;
// Next 8 unknown
cntr += 8;
// Next 16 padding with FFFFFFFF
cntr += 8;
// 20 to 22 length of File Name
var fileNameLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 2;
// Next 126 as System Name
var fileName = utils_1.hex2ascii(stream.substr(cntr, fileNameLength * 2));
cntr += 126;
// Next 16 as padding FFFFFFFF00000000
cntr += 16;
// Next 8 file format
var format = utils_1.hex2ascii(stream.substr(cntr, 8));
cntr += 8;
// Next 16 as padding FFFFFFFF00000000
cntr += 16;
// Next 38 unknown
cntr += 38;
// Next 2 dir name length
var dirNameLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 2;
// Next dirNameLength as Directory Name
var dirName = utils_1.hex2ascii(stream.substr(cntr, dirNameLength * 2));
cntr += dirNameLength * 2;
// Weird padding based on odd or even
cntr += dirNameLength % 2 == 0 ? 2 : 4;
// Next 4 unknown
cntr += 4;
// Next 2 location length
var locationLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 2;
// Next locationLength as Location
var locationRaw = utils_1.hex2ascii(stream.substr(cntr, locationLength * 2));
cntr += locationLength * 2;
var location = locationRaw.substr(2).split(':').join('/');
return new FilerefData(systemName, location, format);
}
exports.unmarshall = unmarshall;
function marshall(data) {
// Starting 8 Padding, 4 total length, 6 unknown
var stream = '00000000000000020000';
// 1 size, 63 system name
stream += utils_1.dec2hex(data.getSystemName().length);
stream += utils_1.ascii2hex(data.getSystemName()).padEnd(62, '0');
// Unknown 8, buffer 8
stream += '42440001FFFFFFFF';
// 1 size, 126 file name
stream += utils_1.dec2hex(data.getFileName().length);
stream += utils_1.ascii2hex(data.getFileName()).padEnd(126, '0');
// 16 padding
stream += 'FFFFFFFF00000000';
// 8 fileformat
stream += utils_1.ascii2hex(data.getFormat());
// 16 padding
stream += '00000000FFFFFFFF';
// 38 Unknown
stream += '00000A20637500000000000000000000000000';
// 1 size, 63 dir name, weird padding based on length
stream += utils_1.dec2hex(data.getDir().length);
stream += utils_1.ascii2hex(data.getDir());
stream += utils_1.lenPad(data.getDir().length);
// Unknown 4
stream += '0200';
// length + 2, location with delminator :
stream += utils_1.dec2hex(data.getLocation(':').length + 2);
stream += utils_1.ascii2hex('/:' + data.getLocation(':'));
stream += utils_1.lenPad(data.getLocation(':').length);
// Unknown 4
stream += '0E00';
// length of the file name with padding and length header (12*2 + 2 = 26), 2 padding
stream += utils_1.dec2hex((data.getFileName().length * 2) + 2) + '00';
stream += utils_1.dec2hex(data.getFileName().length) + '00';
stream += utils_1.ascii2hex(data.getFileName().split('').join('\0')) + '00';
// Unknown 4
stream += '0F00';
// length of the system name with padding and length header (12*2 + 2 = 26), 2 padding
stream += utils_1.dec2hex((data.getSystemName().length * 2) + 2) + '00';
stream += utils_1.dec2hex(data.getSystemName().length) + '00';
stream += utils_1.ascii2hex(data.getSystemName().split('').join('\0')) + '00';
// Unknown 4
stream += '1200';
stream += utils_1.dec2hex(data.getLocation('/').length);
stream += utils_1.ascii2hex(data.getLocation('/'));
stream += utils_1.lenPad(data.getLocation('/').length);
// Unknwon end
stream += '1300012F00001500020015FFFF0000';
var lenStr = utils_1.dec2hex(stream.length / 2);
stream = utils_1.replaceAt(stream, lenStr, 8);
return stream;
}
exports.marshall = marshall;
6 changes: 6 additions & 0 deletions build/lib/fileref-data/utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export declare function ascii2hex(str: string): string;
export declare function hex2ascii(hex: string): string;
export declare function hex2dec(hex: string): number;
export declare function dec2hex(dec: number): string;
export declare function lenPad(len: number): "00" | "0000";
export declare function replaceAt(str: string, rep: string, index: number): string;
44 changes: 44 additions & 0 deletions build/lib/fileref-data/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function ascii2hex(str) {
var hex = '';
for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
var char = str_1[_i];
var res = char.charCodeAt(0).toString(16);
hex += res == '0' ? '00' : res;
}
return hex.toUpperCase();
}
exports.ascii2hex = ascii2hex;
function hex2ascii(hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2) {
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
}
return str;
}
exports.hex2ascii = hex2ascii;
function hex2dec(hex) {
return parseInt(hex, 16);
}
exports.hex2dec = hex2dec;
function dec2hex(dec) {
var hex = dec.toString(16).toUpperCase();
if (hex.length % 2 == 1)
return '0' + hex;
else
return hex;
}
exports.dec2hex = dec2hex;
function lenPad(len) {
return len % 2 == 0 ? '00' : '0000';
}
exports.lenPad = lenPad;
function replaceAt(str, rep, index) {
var arr = str.split('');
for (var i = 0; i < rep.length; i++) {
arr[index + i] = rep[i];
}
return arr.join('');
}
exports.replaceAt = replaceAt;
13 changes: 9 additions & 4 deletions build/lib/fileref/fileref-data.d.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
export declare class FilerefData {
header: string;
systemName: string;
location: string;
diskName: string;
relativeLocation: string;
footer: string;
constructor(header: string, systemName: string, location: string, footer: string);
external: boolean;
diskLocation: string;
constructor(header: string, diskName: string, relativeLocation: string, footer: string, external: boolean, diskLocation: string);
getFileName(): string;
getDir(): string;
getLocation(delminator: string): string;
getSystemName(): string;
getRelativeLocation(delminator: string): string;
getDiskLocation(delminator: string): string;
getDiskName(): string;
getHeader(): string;
getFooter(): string;
isExternal(): boolean;
setLocation(location: string): void;
}
export declare function unmarshall(stream: string): FilerefData;
Expand Down
85 changes: 58 additions & 27 deletions build/lib/fileref/fileref-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
var path_1 = __importDefault(require("path"));
var utils_1 = require("./utils");
var FilerefData = /** @class */ (function () {
function FilerefData(header, systemName, location, footer) {
function FilerefData(header, diskName, relativeLocation, footer, external, diskLocation) {
this.header = header;
this.systemName = systemName;
this.location = location;
this.diskName = diskName;
this.relativeLocation = relativeLocation;
this.footer = footer;
this.external = external;
this.diskLocation = diskLocation;
}
FilerefData.prototype.getFileName = function () {
return path_1.default.parse(this.location).base;
return path_1.default.parse(this.relativeLocation).base;
};
FilerefData.prototype.getDir = function () {
return path_1.default.basename(path_1.default.dirname(this.location));
return path_1.default.basename(path_1.default.dirname(this.relativeLocation));
};
FilerefData.prototype.getLocation = function (delminator) {
return this.location.split(path_1.default.sep).join(delminator);
return path_1.default.join(this.diskLocation, this.relativeLocation).split(path_1.default.sep).join(delminator);
};
FilerefData.prototype.getSystemName = function () {
return this.systemName;
FilerefData.prototype.getRelativeLocation = function (delminator) {
return this.relativeLocation.split(path_1.default.sep).join(delminator);
};
FilerefData.prototype.getDiskLocation = function (delminator) {
return this.diskLocation.split(path_1.default.sep).join(delminator);
};
FilerefData.prototype.getDiskName = function () {
return this.diskName;
};
FilerefData.prototype.getHeader = function () {
return this.header;
};
FilerefData.prototype.getFooter = function () {
return this.footer;
};
FilerefData.prototype.isExternal = function () {
return this.external;
};
FilerefData.prototype.setLocation = function (location) {
// Store the absolute location but donot have the deliminator in the start
/*
Currently we by default convert every location to absolute and
store it as an internal file. In futre we might break the lcoation
to disk location and relative location.
*/
location = path_1.default.resolve(location);
if (location[0] == path_1.default.sep)
location = location.substr(1);
this.location = location;
this.relativeLocation = location;
this.diskLocation = '/';
this.external = false;
};
return FilerefData;
}());
Expand Down Expand Up @@ -85,17 +102,17 @@ function unmarshall(stream) {
cntr += 4;
// Length of total sytem name length blob, 2 padding
cntr += 4;
// length of system name string, 2 padding
var systemNameLength = utils_1.hex2dec(stream.substr(cntr, 2));
// length of disk name string, 2 padding
var diskNameLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 4;
// Name length with each char with 2 padding
var systemName = utils_1.hex2ascii(stream.substr(cntr, systemNameLength * 4));
cntr += systemNameLength * 4;
var diskName = utils_1.hex2ascii(stream.substr(cntr, diskNameLength * 4));
cntr += diskNameLength * 4;
// Next 4 control code
if (stream.substr(cntr, 4) != '1200')
throw Error("Data of the ref cannot be recognised: 1200");
cntr += 4;
// length of system name string
// length of disk name string
locationLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 2;
// Name length with each char with 2 padding
Expand All @@ -105,19 +122,29 @@ function unmarshall(stream) {
// Next 4 control code
if (stream.substr(cntr, 4) != '1300')
throw Error("Data of the ref cannot be recognised: 1300");
// TODO: The footer would go down
cntr += 4;
var diskLocationLength = utils_1.hex2dec(stream.substr(cntr, 2));
cntr += 2;
var diskLocation = utils_1.hex2ascii(stream.substr(cntr, diskLocationLength * 2));
// TODO: Not sure if this works with windows
var isExternal = diskLocation != '/';
cntr += diskLocationLength * 2;
var footer = stream.substr(cntr);
return new FilerefData(header, systemName, location, footer);
return new FilerefData(header, diskName, location, footer, isExternal, diskLocation);
}
exports.unmarshall = unmarshall;
function marshall(data) {
if (data.external)
throw "Parser doesn't support marshalling external fileref";
// Starting 8 Padding, 4 total length, 6 unknown
var stream = data.getHeader();
// Control Code
stream += '0200';
// length + 2, location with delminator :
stream += utils_1.dec2hex(data.getLocation(':').length + 2);
stream += utils_1.ascii2hex('/:' + data.getLocation(':'));
stream += utils_1.lenPad(data.getLocation(':').length);
stream += utils_1.dec2hex(data.getRelativeLocation(':').length + 2);
stream += utils_1.ascii2hex('/:' + data.getRelativeLocation(':'));
stream += utils_1.lenPad(data.getRelativeLocation(':').length);
// Control Code
stream += '0E00';
// length of the file name with padding and length header (12*2 + 2 = 26), 2 padding
Expand All @@ -126,16 +153,20 @@ function marshall(data) {
stream += utils_1.ascii2hex(data.getFileName().split('').join('\0')) + '00';
// Control Code
stream += '0F00';
// length of the system name with padding and length header (12*2 + 2 = 26), 2 padding
stream += utils_1.dec2hex((data.getSystemName().length * 2) + 2) + '00';
stream += utils_1.dec2hex(data.getSystemName().length) + '00';
stream += utils_1.ascii2hex(data.getSystemName().split('').join('\0')) + '00';
// length of the disk name with padding and length header (12*2 + 2 = 26), 2 padding
stream += utils_1.dec2hex((data.getDiskName().length * 2) + 2) + '00';
stream += utils_1.dec2hex(data.getDiskName().length) + '00';
stream += utils_1.ascii2hex(data.getDiskName().split('').join('\0')) + '00';
// Control Code
stream += '1200';
stream += utils_1.dec2hex(data.getLocation('/').length);
stream += utils_1.ascii2hex(data.getLocation('/'));
stream += utils_1.lenPad(data.getLocation('/').length);
// Unknwon end
stream += utils_1.dec2hex(data.getRelativeLocation('/').length);
stream += utils_1.ascii2hex(data.getRelativeLocation('/'));
stream += utils_1.lenPad(data.getRelativeLocation('/').length);
// Control Code
stream += '1300';
stream += utils_1.dec2hex(data.getDiskLocation('/').length);
stream += utils_1.ascii2hex(data.getDiskLocation('/'));
// Unknown end
stream += data.getFooter();
// Total size update
var lenStr = utils_1.dec2hex(stream.length / 2);
Expand Down
Loading